📄 acts.c
字号:
}
else if( Cur_nonterm >= MAXNONTERM )
{
lerror(FATAL, "Too many nonterminal symbols (%d max.).\n", MAXTERM );
}
else /* Add new nonterminal to symbol table */
{
p = (SYMBOL *) newsym( sizeof(SYMBOL) );
strncpy ( p->name, name, NAME_MAX );
strncpy ( p->field, Field_name, NAME_MAX );
p->val = ++Cur_nonterm ;
Terms[Cur_nonterm] = p;
addsym ( Symtab, p );
}
if( p ) /* (re)initialize new nonterminal */
{
if( Goal_symbol_is_next )
{
Goal_symbol = p;
Goal_symbol_is_next = 0;
}
if( !p->first )
p->first = newset();
LL( if( !p->follow ) )
LL( p->follow = newset(); )
p->lineno = yylineno ;
if( is_lhs )
{
strncpy( Sp->lhs_name, name, NAME_MAX );
Sp->lhs = p ;
Sp->rhs = NULL;
Sp->lhs->set = yylineno;
}
}
return p;
}
/*----------------------------------------------------------------------*/
PUBLIC void new_rhs()
{
/* Get a new PRODUCTION and link it to the head of the production chain.
* of the current nonterminal. Note that the start production MUST be
* production 0. As a consequence, the first rhs associated with the first
* nonterminal MUST be the start production. Num_productions is initialized
* to 0 when it's declared.
*/
PRODUCTION *p;
if( !(p = (PRODUCTION *) calloc(1, sizeof(PRODUCTION))) )
lerror(FATAL, "No memory for new right-hand side\n");
p->next = Sp->lhs->productions;
Sp->lhs->productions = p;
LL( p->select = newset(); )
if( (p->num = Num_productions++) >= MAXPROD )
lerror(FATAL, "Too many productions (%d max.)\n", MAXPROD );
p->lhs = Sp->lhs;
Sp->rhs = p;
}
/*----------------------------------------------------------------------*/
PUBLIC void add_to_rhs( object, is_an_action )
char *object;
int is_an_action; /* 0 of not an action, line number otherwise */
{
SYMBOL *p;
int i;
char buf[32];
/* Add a new element to the RHS currently at top of stack. First deal with
* forward references. If the item isn't in the table, add it. Note that,
* since terminal symbols must be declared with a %term directive, forward
* references always refer to nonterminals or action items. When we exit the
* if statement, p points at the symbol table entry for the current object.
*/
if( !(p = (SYMBOL *) findsym( Symtab, object)) ) /* not in tab yet */
{
if( !is_an_action )
{
if( !(p = new_nonterm( object, 0 )) )
{
/* Won't get here unless p is a terminal symbol */
lerror(FATAL, "(internal) Unexpected terminal symbol\n");
return;
}
}
else
{
/* Add an action. All actions are named "{DDD}" where DDD is the
* action number. The curly brace in the name guarantees that this
* name won't conflict with a normal name. I am assuming that calloc
* is used to allocate memory for the new node (ie. that it's
* initialized to zeros).
*/
sprintf(buf, "{%d}", ++Cur_act - MINACT );
p = (SYMBOL *) newsym( sizeof(SYMBOL) );
strncpy ( p->name, buf, NAME_MAX );
addsym ( Symtab, p );
p->val = Cur_act ;
p->lineno = is_an_action ;
if( !(p->string = strdup(object)) )
lerror(FATAL, "Insufficient memory to save action\n");
}
}
p->used = yylineno;
if( (i = Sp->rhs->rhs_len++) >= MAXRHS )
lerror(NONFATAL, "Right-hand side too long (%d max)\n", MAXRHS );
else
{
LL( if( i == 0 && p == Sp->lhs ) )
LL( lerror(NONFATAL, "Illegal left recursion in production.\n");)
OX( if( ISTERM( p ) ) )
OX( Sp->rhs->prec = Precedence[ p->val ].level ; )
Sp->rhs->rhs[ i ] = p;
Sp->rhs->rhs[ i + 1 ] = NULL; /* NULL terminate the array. */
if( !ISACT(p) )
++( Sp->rhs->non_acts );
}
}
/*----------------------------------------------------------------------
* The next two subroutines handle repeating or optional subexpressions. The
* following mappings are done, depending on the operator:
*
* S : A [B] C ; S -> A 001 C
* 001 -> B | epsilon
*
* S : A [B]* C ; S -> A 001 C (occs)
* 001 -> 001 B | epsilon
*
* S : A [B]* C ; S -> A 001 C (llama)
* 001 -> B 001 | epsilon
*
* In all situations, the right hand side that we've collected so far is
* pushed and a new right-hand side is started for the subexpression. Note that
* the first character of the created rhs name (001 in the previous examples)
* is a space, which is illegal in a user-supplied production name so we don't
* have to worry about conflicts. Subsequent symbols are added to this new
* right-hand side. When the ), ], or *) is found, we finish the new right-hand
* side, pop the stack and add the name of the new right-hand side to the
* previously collected left-hand side.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
PUBLIC void start_opt( lex ) /* Start an optional subexpression */
char *lex; /* not used at present, but might be. */
{
char name[32];
static int num = 0;
--Sp; /* Push current stack element */
sprintf( name, " %06d", num++); /* Make name for new production */
new_nonterm( name, 1 ); /* Create a nonterminal for it. */
new_rhs(); /* Create epsilon production. */
new_rhs(); /* and production for sub-prod. */
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void end_opt( lex ) /* end optional subexpression */
char *lex;
{
char *name = Sp->lhs_name ;
OX( int i; )
OX( SYMBOL *p; )
if( lex[1] == '*' ) /* Process a [...]* */
{
add_to_rhs( name, 0 ); /* Add right-recursive reference. */
#ifdef OCCS /* If occs, must be left recursive.*/
i = Sp->rhs->rhs_len - 1; /* Shuffle things around. */
p = Sp->rhs->rhs[ i ];
memmove( &(Sp->rhs->rhs)[1], &(Sp->rhs->rhs)[0],
i * sizeof( (Sp->rhs->rhs)[1] ) );
Sp->rhs->rhs[ 0 ] = p ;
#endif
}
++Sp; /* discard top-of-stack element */
add_to_rhs( name, 0 );
}
/*======================================================================
* The following routines have alternate versions, one set for llama and another
* for occs. The routines corresponding to features that aren't supported in one
* or the other of these programs print error messages.
*/
#ifdef LLAMA
PUBLIC void add_synch( name )
char *name;
{
/* Add "name" to the set of synchronization tokens
*/
SYMBOL *p;
if( !(p = (SYMBOL *) findsym( Symtab, name )) )
lerror(NONFATAL,"%%synch: undeclared symbol <%s>.\n", name );
else if( !ISTERM(p) )
lerror(NONFATAL,"%%synch: <%s> not a terminal symbol\n", name );
else
ADD( Synch, p->val );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void new_lev( how )
int how;
{
switch( how )
{
case 0 : /* initialization: ignore it */ break;
case 'l': lerror (NONFATAL, "%%left not recognized by LLAMA\n" ); break;
case 'r': lerror (NONFATAL, "%%right not recognized by LLAMA\n" ); break;
default : lerror (NONFATAL, "%%nonassoc not recognized by LLAMA\n"); break;
}
}
PUBLIC void prec( name )
char *name;
{
lerror( NONFATAL, "%%prec %s not recognized by LLAMA\n", name );
}
#ifdef __TURBOC__
#pragma argsused
#endif
PUBLIC void union_def( action )
char *action;
{
lerror(NONFATAL,"%%union not recognized by LLAMA\n");
}
#ifdef __TURBOC__
#pragma argsused
#endif
PUBLIC void prec_list( name ) char *name;
{
}
PUBLIC void new_field( field_name )
char *field_name;
{
if( *field_name )
lerror(NONFATAL, "<name> not supported by LLAMA\n");
}
#else /*============================================================*/
#ifdef __TURBOC__
#pragma argsused
#endif
PUBLIC void add_synch(yytext)
char *yytext;
{
lerror(NONFATAL, "%%synch not supported by OCCS\n");
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void new_lev( how )
int how;
{
/* Increment the current precedence level and modify "Associativity"
* to remember if we're going left, right, or neither.
*/
if( Associativity = how ) /* 'l', 'r', 'n', (0 if unspecified) */
++Prec_lev;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void prec_list( name )
char *name;
{
/* Add current name (in yytext) to the precision list. "Associativity" is
* set to 'l', 'r', or 'n', depending on whether we're doing a %left,
* %right, or %nonassoc. Also make a nonterminal if it doesn't exist
* already.
*/
SYMBOL *sym;
if( !(sym = (SYMBOL *) findsym(Symtab,name)) )
sym = make_term( name );
if( !ISTERM(sym) )
lerror(NONFATAL, "%%left or %%right, %s must be a token\n", name );
else
{
Precedence[ sym->val ].level = Prec_lev ;
Precedence[ sym->val ].assoc = Associativity ;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void prec( name )
char *name;
{
/* Change the precedence level for the current right-hand side, using
* (1) an explicit number if one is specified, or (2) an element from the
* Precedence[] table otherwise.
*/
SYMBOL *sym;
if( isdigit(*name) )
Sp->rhs->prec = atoi(name); /* (1) */
else
{
if( !(sym = (SYMBOL *) findsym(Symtab,name)) )
lerror(NONFATAL, "%s (used in %%prec) undefined\n" );
else if( !ISTERM(sym) )
lerror(NONFATAL, "%s (used in %%prec) must be terminal symbol\n" );
else
Sp->rhs->prec = Precedence[ sym->val ].level; /* (2) */
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void union_def( action )
char *action;
{
/* create a YYSTYPE definition for the union, using the fields specified
* in the %union directive, and also appending a default integer-sized
* field for those situation where no field is attached to the current
* symbol.
*/
while( *action && *action != '{' ) /* Get rid of everything up to the */
++action; /* open brace */
if( *action ) /* and the brace itself */
++action;
output( "typedef union\n" );
output( "{\n" );
output( " int %s; /* Default field, used when no %%type found */",
DEF_FIELD );
output( "%s\n", action );
output( "yystype;\n\n" );
output( "#define YYSTYPE yystype\n" );
Fields_active = 1;
}
ANSI( PUBLIC int fields_active( void ) )
KnR ( PUBLIC int fields_active( ) )
{
return Fields_active ; /* previous %union was specified */
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void new_field( field_name )
char *field_name;
{
/* Change the name of the current <field> */
char *p;
if( !*field_name )
*Field_name = '\0' ;
else
{
if( p = strchr(++field_name, '>') )
*p = '\0' ;
strncpy( Field_name, field_name, sizeof(Field_name) );
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -