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

📄 llpar.c

📁 一个c语言写做的编译器的源码
💻 C
字号:
/*@A (C) 1992 Allen I. Holub                                                */
#include <stdio.h>
#include <stdarg.h>
#include <tools/debug.h>
#include <tools/set.h>
#include <tools/hash.h>
#include <tools/compiler.h>
#include <tools/l.h>

#include "llout.h"
#include "parser.h"

/* LLPAR.C:	A recursive-descent parser for a very stripped down llama.
 *		There's a llama input specification for a table-driven parser
 *		in llama.lma.
 */

void advance	 P(( void 		));	/* local */
void lookfor	 P(( int first,...	));
void definitions P(( void 		));
void body	 P(( void 		));
void right_sides P(( void 		));
void rhs	 P(( void 		));
int  yyparse	 P(( void 		));	/* public */
extern int	yylineno;			/* Created by lex.*/
extern char	*yytext;
extern int	yylex P((void));
/*----------------------------------------------------------------------*/

PUBLIC  int yynerrs;		/* Total error count		*/
PRIVATE int Lookahead;		/* Lookahead token	    	*/

/*======================================================================
 * Low-level support routines for parser:
 */

#define match(x) ((x) == Lookahead)

PRIVATE	void advance()
{
    if( Lookahead != _EOI_ )
	while( (Lookahead = yylex()) == WHITESPACE )
		;
}
/*----------------------------------------------------------------------*/
ANSI( PRIVATE	void	lookfor( int first, ... )	)
KnR ( PRIVATE	void	lookfor(     first      )	)
KnR ( int	first;					)
{
    /* Read input until the current symbol is in the argument list. For example,
     * lookfor(OR, SEMI, 0) terminates when the current Lookahead symbol is an
     * OR or SEMI. Searching starts with the next (not the current) symbol.
     */

    int	*obj;

    for( advance() ;; advance() )
    {
	for( obj = &first;  *obj  &&  !match(*obj) ; obj++ )
	    ;

	if( *obj )
	    break;		/* Found a match */

	else if( match(_EOI_) )
	    lerror(FATAL, "Unexpected end of file\n");
    }
}
/*======================================================================
 * The Parser itself
 */

PUBLIC	int yyparse P(( void ))   /* spec : definitions body stuff */
{
	extern yylineno;
	Lookahead = yylex();	   /* Get first input symbol */
	definitions();
	first_sym();
	body();
	return 0;
}
/*----------------------------------------------------------------------*/
PRIVATE	void	definitions()
{
    /*								implemented at:
     * definitions  : TERM_SPEC tnames  definitions			1
     *		    | CODE_BLOCK 	definitions			2
     *		    | SYNCH snames      definitions			3
     *		    | SEPARATOR						4
     *		    | _EOI_						4
     * snames	    : NAME {add_synch} snames				5
     * tnames	    : NAME {make_term} tnames				6
     *
     * Note that LeX copies the CODE_BLOCK contents to the output file
     * automatically on reading it.
     */

    while( !match(SEPARATOR) && !match(_EOI_) )				/* 4 */
    {
	if( Lookahead == SYNCH )					/* 3 */
	{
	    for( advance(); match(NAME); advance() )			/* 5 */
		add_synch( yytext );
	}
	else if( Lookahead == TERM_SPEC )				/* 1 */
	{
	    for( advance(); match(NAME); advance() )			/* 6 */
		make_term( yytext );
	}
	else if( Lookahead == CODE_BLOCK )				/* 2 */
	{
	    advance(); 	/* the block is copied out from yylex() */
	}
	else
	{
	    lerror(NONFATAL,"Ignoring illegal <%s> in definitions\n", yytext );
	    advance();
	}
    }

    advance();					/* advance past the %%	*/
}
/*----------------------------------------------------------------------*/
PRIVATE	void	body()
{
    /*								implemented at:
     * body	: rule body						1
     *		| rule SEPARATOR					1
     *		| rule _EOI_						1
     * rule	: NAME {new_nonterm} COLON right_sides			2
     *		: <epsilon>						3
     */

    extern void ws P(( void ));		/* from lexical analyser */

    while( !match(SEPARATOR)  &&  !match(_EOI_) )			/* 1 */
    {
	if( match(NAME) )						/* 2 */
	{
	    new_nonterm( yytext, 1 );
	    advance();
	}
	else								/* 3 */
	{
	    lerror(NONFATAL, "Illegal <%s>, nonterminal expected.\n", yytext);
	    lookfor( SEMI, SEPARATOR, 0 );
	    if( match(SEMI) )
		advance();
	    continue;
	}

	if( match( COLON ) )
	    advance();
	else
	    lerror(NONFATAL, "Inserted missing ':'\n");

	right_sides();
    }
    ws();			       /* Enable white space (see parser.lex) */
    if( match(SEPARATOR)  )
	yylex();		       /* Advance past %% 		      */
}
/*----------------------------------------------------------------------*/
PRIVATE	void	right_sides()
{
    /* right_sides	: {new_rhs} rhs OR right_sides			1
     *			| {new_rhs} rhs SEMI				2
     */

    new_rhs();
    rhs();
    while( match(OR) )							/* 1 */
    {
	advance();
	new_rhs();
	rhs();
    }
    if( match(SEMI) )							/* 2 */
	advance();
    else
	lerror(NONFATAL, "Inserted missing semicolon\n");
}
/*----------------------------------------------------------------------*/
PRIVATE	void	rhs()
{
    /* rhs	: NAME   {add_to_rhs} rhs  */
    /*		| ACTION {add_to_rhs} rhs  */

    while( match(NAME) || match(ACTION) )
    {
	add_to_rhs( yytext, match(ACTION) ? start_action() : 0 );
	advance();
    }
    if( !match(OR) && !match(SEMI) )
    {
	lerror(NONFATAL, "illegal <%s>, ignoring rest of production\n", yytext);
	lookfor( SEMI, SEPARATOR, OR, 0 );
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -