⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acts.c

📁 its about compiler for LL1 and LR
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
    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 + -