build.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 814 行 · 第 1/2 页
C
814 行
/*
* Make a graph into subblock
*
* makeBlk(G) ::= --o-->o-G-o-->o--
*
* The node on the far right is added so that every block owns its own
* EndBlk node.
*/
Graph
#ifdef __USE_PROTOS
makeBlk( Graph g1, int approx, char * pFirstSetSymbol )
#else
makeBlk( g1, approx, pFirstSetSymbol )
Graph g1;
int approx;
char * pFirstSetSymbol;
#endif
{
Junction *j,*j2;
Graph g;
require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph");
j = newJunction();
j2 = newJunction();
((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */
g1.right = (Node *)j2;
SetBlk(g1, aSubBlk, approx, pFirstSetSymbol);
j->p1 = g1.left; /* add node in front */
g.left = (Node *) j;
g.right = g1.right;
return g;
}
/*
* Make a subgraph into a loop (closure) block -- (...)*
*
* makeLoop(G) ::= |---|
* v |
* --o-->o-->o-G-o-->o--
* | ^
* v |
* o-----------o
*
* After making loop, always place generic node out front. It becomes
* the start of enclosing block. The aLoopBlk is the target of the loop.
*
* Loop blks have TWO EndBlk nodes--the far right and the node that loops back
* to the aLoopBlk node. Node with which we can branch past loop == aLoopBegin and
* one which is loop target == aLoopBlk.
* The branch-past (initial) aLoopBegin node has end
* pointing to the last EndBlk node. The loop-target node has end==NULL.
*
* Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node.
*/
Graph
#ifdef __USE_PROTOS
makeLoop( Graph g1, int approx, char * pFirstSetSymbol )
#else
makeLoop( g1, approx, pFirstSetSymbol)
Graph g1;
int approx;
char * pFirstSetSymbol;
#endif
{
Junction *back, *front, *begin;
Graph g;
require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph");
back = newJunction();
front = newJunction();
begin = newJunction();
g = emptyAlt3();
((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */
((Junction *)g1.right)->p1 = (Node *) back; /* add node to G at end */
((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */
((Junction *)g1.left)->jtype = aLoopBlk; /* mark 2nd aLoopBlk node */
((Junction *)g1.left)->end = (Junction *) g1.right;
((Junction *)g1.left)->lock = makelocks();
((Junction *)g1.left)->pred_lock = makelocks();
g1.right = (Node *) back;
begin->p1 = (Node *) g1.left;
g1.left = (Node *) begin;
begin->p2 = (Node *) g.left; /* make bypass arc */
((Junction *)g.right)->p1 = (Node *) back;
SetBlk(g1, aLoopBegin, approx, pFirstSetSymbol);
front->p1 = g1.left; /* add node to front */
g1.left = (Node *) front;
return g1;
}
/*
* Make a subgraph into a plus block -- (...)+ -- 1 or more times
*
* makePlus(G) ::= |---|
* v |
* --o-->o-G-o-->o--
*
* After making loop, always place generic node out front. It becomes
* the start of enclosing block. The aPlusBlk is the target of the loop.
*
* Plus blks have TWO EndBlk nodes--the far right and the node that loops back
* to the aPlusBlk node.
*
* Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node.
*/
Graph
#ifdef __USE_PROTOS
makePlus( Graph g1, int approx, char * pFirstSetSymbol)
#else
makePlus( g1, approx, pFirstSetSymbol)
Graph g1;
int approx;
char * pFirstSetSymbol;
#endif
{
int has_empty_alt_already = 0;
Graph g;
Junction *j2, *j3, *first_alt;
Junction *last_alt=NULL, *p;
require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph");
first_alt = (Junction *)g1.left;
j2 = newJunction();
j3 = newJunction();
if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */
((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */
((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */
g1.right = (Node *) j2;
SetBlk(g1, aPlusBlk, approx, pFirstSetSymbol);
((Junction *)g1.left)->lock = makelocks();
((Junction *)g1.left)->pred_lock = makelocks();
j3->p1 = g1.left; /* add node to front */
g1.left = (Node *) j3;
/* add an optional branch which is the "exit" branch of loop */
/* FIRST, check to ensure that there does not already exist
* an optional path.
*/
/* find last alt */
for(p=first_alt; p!=NULL; p=(Junction *)p->p2)
{
if ( p->p1->ntype == nJunction &&
p->p1!=NULL &&
((Junction *)p->p1)->jtype==Generic &&
((Junction *)p->p1)->p1!=NULL &&
((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk )
{
has_empty_alt_already = 1;
}
last_alt = p;
}
if ( !has_empty_alt_already )
{
require(last_alt!=NULL, "last_alt==NULL; bad (..)+");
g = emptyAlt();
last_alt->p2 = g.left;
((Junction *)g.right)->p1 = (Node *) j2;
/* make sure lookahead computation ignores this alt for
* FIRST("(..)+"); but it's still used for computing the FIRST
* of each alternative.
*/
((Junction *)g.left)->ignore = 1;
}
return g1;
}
/*
* Return an optional path: --o-->o--
*/
Graph
#ifdef __USE_PROTOS
emptyAlt( void )
#else
emptyAlt( )
#endif
{
Junction *j1, *j2;
Graph g;
j1 = newJunction();
j2 = newJunction();
j1->p1 = (Node *) j2;
g.left = (Node *) j1;
g.right = (Node *) j2;
return g;
}
/* MR21
*
* There is code in genBlk which recognizes the node created
* by emptyAlt() as a special case and bypasses it. We don't
* want this to happen for the optBlk.
*/
Graph
#ifdef __USE_PROTOS
emptyAlt3( void )
#else
emptyAlt3( )
#endif
{
Junction *j1, *j2, *j3;
Graph g;
j1 = newJunction();
j2 = newJunction();
j3 = newJunction();
j1->p1 = (Node *) j2;
j2->p1 = (Node *) j3;
g.left = (Node *) j1;
g.right = (Node *) j3;
return g;
}
/* N o d e A l l o c a t i o n */
TokNode *
#ifdef __USE_PROTOS
newTokNode( void )
#else
newTokNode( )
#endif
{
static TokNode *FreeList = NULL;
TokNode *p, *newblk;
if ( FreeList == NULL )
{
newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode));
if ( newblk == NULL )
fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++)
{
p->next = (Node *)FreeList; /* add all new token nodes to FreeList */
FreeList = p;
}
}
p = FreeList;
FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */
p->next = NULL; /* NULL the ptr we used */
memset( (char *) p, 0, sizeof(TokNode)); /* MR10 */
p->ntype = nToken;
p->rname = CurRule;
p->file = CurFile;
p->line = zzline;
p->altstart = NULL;
return p;
}
RuleRefNode *
#ifdef __USE_PROTOS
newRNode( void )
#else
newRNode( )
#endif
{
static RuleRefNode *FreeList = NULL;
RuleRefNode *p, *newblk;
if ( FreeList == NULL )
{
newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode));
if ( newblk == NULL )
fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++)
{
p->next = (Node *)FreeList; /* add all new rref nodes to FreeList */
FreeList = p;
}
}
p = FreeList;
FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */
p->next = NULL; /* NULL the ptr we used */
memset( (char *) p, 0, sizeof(RuleRefNode)); /* MR10 */
p->ntype = nRuleRef;
p->rname = CurRule;
p->file = CurFile;
p->line = zzline;
p->astnode = ASTinclude;
p->altstart = NULL;
return p;
}
static int junctionSeqNumber=0; /* MR10 */
Junction *
#ifdef __USE_PROTOS
newJunction( void )
#else
newJunction( )
#endif
{
static Junction *FreeList = NULL;
Junction *p, *newblk;
if ( FreeList == NULL )
{
newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction));
if ( newblk == NULL )
fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++)
{
p->p1 = (Node *)FreeList; /* add all new Junction nodes to FreeList */
FreeList = p;
}
}
p = FreeList;
FreeList = (Junction *)FreeList->p1;/* remove a Junction node */
p->p1 = NULL; /* NULL the ptr we used */
memset( (char *) p, 0, sizeof(Junction)); /* MR10 */
p->ntype = nJunction;
p->visited = 0;
p->jtype = Generic;
p->rname = CurRule;
p->file = CurFile;
p->line = zzline;
p->exception_label = NULL;
p->fset = (set *) calloc(CLL_k+1, sizeof(set));
require(p->fset!=NULL, "cannot allocate fset in newJunction");
p->seq=++junctionSeqNumber; /* MR10 */
return p;
}
ActionNode *
#ifdef __USE_PROTOS
newActionNode( void )
#else
newActionNode( )
#endif
{
static ActionNode *FreeList = NULL;
ActionNode *p, *newblk;
if ( FreeList == NULL )
{
newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode));
if ( newblk == NULL )
fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++)
{
p->next = (Node *)FreeList; /* add all new Action nodes to FreeList */
FreeList = p;
}
}
p = FreeList;
FreeList = (ActionNode *)FreeList->next;/* remove an Action node */
memset( (char *) p, 0, sizeof(ActionNode)); /* MR10 */
p->ntype = nAction;
p->next = NULL; /* NULL the ptr we used */
p->done = 0;
p->pred_fail = NULL;
p->guardpred = NULL;
p->ampersandPred = NULL;
return p;
}
/*
* allocate the array of locks (1..CLL_k) used to inhibit infinite recursion.
* Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs.
* Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes.
*
* if ( lock[k]==TRUE ) then we have been here before looking for k tokens
* of lookahead.
*/
char *
#ifdef __USE_PROTOS
makelocks( void )
#else
makelocks( )
#endif
{
char *p = (char *) calloc(CLL_k+1, sizeof(char));
require(p!=NULL, "cannot allocate lock array");
return p;
}
#if 0
** #ifdef __USE_PROTOS
** void my_memset(char *p,char value,int count)
** #else
** void my_memset(p,value,count)
** char *p;
** char value;
** int count;
** #endif
** {
** int i;
**
** for (i=0; i<count; i++) {
** p[i]=value;
** };
** }
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?