build.c revision 4fd606d1f5abe38e1f42c38de1d2e895166bd0f4
/*
* build.c -- functions associated with building syntax diagrams.
*
* SOFTWARE RIGHTS
*
* We reserve no LEGAL rights to the Purdue Compiler Construction Tool
* Set (PCCTS) -- PCCTS is in the public domain. An individual or
* company may do whatever they wish with source code distributed with
* PCCTS or the code generated by PCCTS, including the incorporation of
* PCCTS, or its output, into commerical software.
*
* We encourage users to develop software with PCCTS. However, we do ask
* that credit is given to us for developing PCCTS. By "credit",
* we mean that if you incorporate our source code into one of your
* programs (commercial product, research project, or otherwise) that you
* acknowledge this fact somewhere in the documentation, research report,
* etc... If you like PCCTS and have developed a nice tool with the
* output, please mention that you developed it using PCCTS. In
* addition, we ask that this header remain intact in our source code.
* As long as these guidelines are kept, we expect to continue enhancing
* this system and expect to make other tools available as they are
* completed.
*
* ANTLR 1.33
* Terence Parr
* Parr Research Corporation
* with Purdue University and AHPCRC, University of Minnesota
* 1989-2001
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "pcctscfg.h"
#include "set.h"
#include "syn.h"
#include "hash.h"
#include "generic.h"
#include "dlgdef.h"
/* Add the parameter string 'parm' to the parms field of a block-type junction
* g.left points to the sentinel node on a block. i.e. g.left->p1 points to
* the actual junction with its jtype == some block-type.
*/
void
#ifdef __USE_PROTOS
#else
Node *p;
char *parm;
#endif
{
{
((RuleRefNode *)p)->parms = q;
}
{
}
else fatal_internal("addParm: invalid node for adding parm");
}
/*
* Build an action node for the syntax diagram
*
* buildAction(ACTION) ::= --o-->ACTION-->o--
*
* Where o is a junction node.
*/
#ifdef __USE_PROTOS
#else
char *action;
int file;
int line;
int is_predicate;
#endif
{
Graph g;
ActionNode *a;
j1 = newJunction();
j2 = newJunction();
a = newActionNode();
a->is_predicate = is_predicate;
if (is_predicate) {
char *t;
char *key;
char *u;
int inverted=0;
for (u=a->action; *u != '\0' ; u++) {
if (*u != ' ') {
if (t==key && *u=='!') {
} else {
*t++=*u;
};
};
};
*t='\0';
} else {
/* MR12c */ char *strEnd;
/* MR12c */ }
}
return g;
}
/*
* Build a token node for the syntax diagram
*
* buildToken(TOKEN) ::= --o-->TOKEN-->o--
*
* Where o is a junction node.
*/
#ifdef __USE_PROTOS
buildToken( char *text )
#else
buildToken( text )
char *text;
#endif
{
Graph g;
TokNode *t;
j1 = newJunction();
j2 = newJunction();
t = newTokNode();
t->altstart = CurAltStart;
return g;
}
/*
* Build a wild-card node for the syntax diagram
*
* buildToken(TOKEN) ::= --o-->'.'-->o--
*
* Where o is a junction node.
*/
#ifdef __USE_PROTOS
buildWildCard( char *text )
#else
char *text;
#endif
{
Graph g;
TokNode *t;
TCnode *w;
TermEntry *p;
j1 = newJunction();
j2 = newJunction();
t = newTokNode();
/* If the ref a wild card, make a token class for it */
if ( Tnum(WildCardString) == 0 )
{
w = newTCnode;
WildCardToken = w->tok;
"hash table mechanism is broken");
p->tclass = w; /* save ptr to this tclass def */
}
else {
w = p->tclass;
}
t->wild_card = 1;
t->tclass = w;
t->altstart = CurAltStart;
return g;
}
void
#ifdef __USE_PROTOS
#else
setUpperRange(t, text)
TokNode *t;
char *text;
#endif
{
}
/*
* Build a rule reference node of the syntax diagram
*
* buildRuleRef(RULE) ::= --o-->RULE-->o--
*
* Where o is a junction node.
*
* If rule 'text' has been defined already, don't alloc new space to store string.
* Set r->text to point to old copy in string table.
*/
#ifdef __USE_PROTOS
buildRuleRef( char *text )
#else
buildRuleRef( text )
char *text;
#endif
{
Graph g;
RuleRefNode *r;
RuleEntry *p;
j1 = newJunction();
j2 = newJunction();
r = newRNode();
r->altstart = CurAltStart;
return g;
}
/*
* Or two subgraphs into one graph via:
*
* Or(G1, G2) ::= --o-G1-o--
* | ^
* v |
* o-G2-o
*
* Set the altnum of junction starting G2 to 1 + altnum of junction starting G1.
* If, however, the G1 altnum is 0, make it 1 and then
* make G2 altnum = G1 altnum + 1.
*/
#ifdef __USE_PROTOS
#else
#endif
{
Graph g;
/* set altnums */
return g;
}
/*
* Catenate two subgraphs
*
* Cat(G1, G2) ::= --o-G1-o-->o-G2-o--
* Cat(NULL,G2)::= --o-G2-o--
* Cat(G1,NULL)::= --o-G1-o--
*/
#ifdef __USE_PROTOS
#else
#endif
{
Graph g;
return g;
}
/*
* Make a subgraph an optional block
*
* makeOpt(G) ::= --o-->o-G-o-->o--
* | ^
* v |
* o-------o
*
* Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found.
*
* The node on the far right is added so that every block owns its own
* EndBlk node.
*/
#ifdef __USE_PROTOS
#else
int approx;
char * pFirstSetSymbol;
#endif
{
Graph g;
j1 = newJunction();
j2 = newJunction();
/* 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.
*/
g = emptyAlt3(); /* MR21 */
{;} /* find last alt */
return g;
}
/*
* 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.
*/
#ifdef __USE_PROTOS
#else
int approx;
char * pFirstSetSymbol;
#endif
{
Graph g;
j = newJunction();
j2 = newJunction();
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.
*/
#ifdef __USE_PROTOS
#else
int approx;
char * pFirstSetSymbol;
#endif
{
Graph g;
back = newJunction();
front = newJunction();
begin = newJunction();
g = emptyAlt3();
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.
*/
#ifdef __USE_PROTOS
#else
int approx;
char * pFirstSetSymbol;
#endif
{
int has_empty_alt_already = 0;
Graph g;
j2 = newJunction();
j3 = newJunction();
/* 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 */
{
{
}
last_alt = p;
}
if ( !has_empty_alt_already )
{
g = emptyAlt();
/* make sure lookahead computation ignores this alt for
* FIRST("(..)+"); but it's still used for computing the FIRST
* of each alternative.
*/
}
return g1;
}
/*
* Return an optional path: --o-->o--
*/
#ifdef __USE_PROTOS
emptyAlt( void )
#else
emptyAlt( )
#endif
{
Graph g;
j1 = newJunction();
j2 = newJunction();
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.
*/
#ifdef __USE_PROTOS
emptyAlt3( void )
#else
emptyAlt3( )
#endif
{
Graph g;
j1 = newJunction();
j2 = newJunction();
j3 = newJunction();
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
{
{
{
FreeList = p;
}
}
p = FreeList;
return p;
}
#ifdef __USE_PROTOS
newRNode( void )
#else
newRNode( )
#endif
{
RuleRefNode *p, *newblk;
{
{
FreeList = p;
}
}
p = FreeList;
p->astnode = ASTinclude;
return p;
}
static int junctionSeqNumber=0; /* MR10 */
Junction *
#ifdef __USE_PROTOS
newJunction( void )
#else
newJunction( )
#endif
{
{
{
FreeList = p;
}
}
p = FreeList;
p->visited = 0;
p->exception_label = NULL;
return p;
}
#ifdef __USE_PROTOS
newActionNode( void )
#else
#endif
{
ActionNode *p, *newblk;
{
{
FreeList = p;
}
}
p = FreeList;
p->done = 0;
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
{
return p;
}
#if 0
** #ifdef __USE_PROTOS
** #else
** char *p;
** char value;
** int count;
** #endif
** {
** int i;
**
** for (i=0; i<count; i++) {
** p[i]=value;
** };
** }
#endif