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

📄 parser.lex

📁 一个c语言写做的编译器的源码
💻 LEX
字号:
/*@A (C) 1992 Allen I. Holub                                                */

%{
#include <stdio.h>
#include <tools/debug.h>
#include <tools/hash.h>
#include <tools/set.h>
#include "llout.h"

#define CREATING_LLAMA_PARSER	/* Suppress various definitions in parser.h */
#include "parser.h"		/* that conflict with LeX-generated defs.   */

/* ----------------------------------------------------------------------
 * Lexical analyzer for both llama and yacc. Note that llama doesn't support
 * %left, %right, %noassoc, or %prec. They are recognized here so that we can
 * print an error message when they're encountered. By the same token, yacc
 * ignores the %synch directive. Though all legal llama input files can be
 * processed by yacc, the reverse is not true.
 *
 * ----------------------------------------------------------------------
 * Whitespace, comments, and otherwise illegal characters must be handled
 * specially. When we're processing code blocks, we need to get at
 * the characters so that they can be passed to the output, otherwise, the
 * characters should be ignored. The ws() and nows() subroutines (at the
 * bottom of the file) switch between these behaviors by changing the value
 * if Ignore. If Ignore is true, white space is ignored.
 */

PRIVATE int   Ignore = 0;
PRIVATE int   Start_line;	/* starting line number  */

/* ----------------------------------------------------------------------
 *  Prototypes for functions at the bottom of this file:
 */

void stripcr P(( char *src ));  /* Remove carriage returns (but not	*/
			      	/* linefeeds) from src.			*/
void nows    P(( void ));	/* Ignore white space, etc 	 	*/
void ws      P(( void )); 	/* Don't ignore white space, etc 	*/
%}

c_name	[A-Za-z_][A-Za-z_0-9]*
%%

"/*"		   {	/* Absorb a comment (treat it as WHITESPACE) */

			int i;
			int start = yylineno;

			while( i = input() )
			{
		           if( i < 0 )
			   {
			      ii_unterm();
			      ii_flush(1);
			      ii_term();
			      lerror(NONFATAL,"Comment starting on line " );
			      lerror(NOHDR,   "%d too long, truncating\n",
			      						start);
			   }
			   else if( i == '*'  &&  ii_lookahead(1) == '/' )
			   {
				input();
				stripcr( yytext );

				if( Ignore ) goto end;
				else	     return WHITESPACE;
			   }
			}

			lerror(FATAL, "End of file encountered in comment\n");

		   end:;
		   }

		   /* Suck up an entire action. Handle nested braces here.
		    * This code won't work if the action is longer than the
		    * buffer length used by the input functions. If this is a
		    * problem, you have to allocate your own buffer and copy
		    * the lexeme there as it's processed (in a manner similar to
		    * the %{ processing, below). If space is really a problem,
		    * the code blocks can be copied to a temporary file and the
		    * offset to the start of the text (as returned by ftell())
		    * can be stored rather than the string itself.
		    */

\{		    {
			int  i;
			int  nestlev;		/* brace-nesting level 	  */
			int  lb1;		/* previous character     */
			int  lb2;		/* character before that  */
			int  in_string;		/* processing string constant */
			int  in_char_const;	/* processing char.  constant */
			int  in_comment;	/* processing a comment	      */

			lb1 = lb2     = 0;
			in_string     = 0;
			in_char_const = 0;
			in_comment    = 0;
			Start_line    = yylineno;

		   	for( nestlev=1; i=input(); lb2=lb1, lb1=i )
			{
			    if( lb2=='\n' && lb1=='%' && i=='%' )
			       lerror( FATAL,
				    "%%%% in code block starting on line %d\n",
				    Start_line );

			    if( i < 0 )		/* input-buffer overflow */
			    {
			      ii_unterm();
			      ii_flush(1);
			      ii_term();
			      lerror( FATAL,
				   "Code block starting on line %d too long.\n",
								    Start_line);
			    }

			    if( i == '\n' && in_string )
			    {
				lerror(WARNING,
					   "Newline in string, inserting \"\n");
				in_string = 0;
			    }

			    /* Take care of \{, "{", '{', \}, "}", '}'  */

			    if( i == '\\' )
			    {
				if( !(i = input()) )	/* discard backslash  */
				    break;
				else
				    continue;		/* and following char */
			    }

			    if( i == '"' && !(in_char_const || in_comment) )
				in_string = !in_string;

			    else if( i == '\'' && !(in_string || in_comment) )
				in_char_const = !in_char_const;

			    else if( lb1 == '/' && i == '*' && !in_string )
				in_comment = 1;

			    else if( lb1 == '*' && i == '/' && in_comment )
				in_comment = 0;

			    if( !(in_string || in_char_const || in_comment) )
			    {
				if( i == '{' )
				    ++nestlev;

				if( i == '}' && --nestlev <= 0 )
				{
				    stripcr( yytext );
				    return ACTION;
				}
			    }
			}

			lerror(FATAL, "EOF in code block starting on line %d\n",
								  Start_line );
		   }

^"%%"		   return SEPARATOR;		/* Must be anchored because  */
						/* it can appear in a printf */
						/* statement.		     */
"%{"[\s\t]*	   {
			/* Copy a code block to the output file.  */

			int c, looking_for_brace = 0;

			#undef output	       /* replace macro with function */
					       /* in main.c		      */
			if( !No_lines )
			    output( "\n#line %d \"%s\"\n",
						    yylineno, Input_file_name );

			while( c = input() )	/* while not at end of file   */
			{
			    if( c == -1 )	/* buffer is full, flush it   */
				ii_flushbuf();

			    else if( c != '\r' )
			    {
				if( looking_for_brace )	/* last char was a %  */
				{					   /*{*/
				    if( c == '}' ) break;
				    else	   output( "%%%c", c );
				    looking_for_brace = 0;
				}
				else
				{
				    if( c == '%' ) looking_for_brace = 1;
				    else	   output( "%c", c );
				}
			    }
			}
			return CODE_BLOCK;
		   }

<{c_name}>	   return FIELD;	  	/* for occs only  	   */
"%union"	   return PERCENT_UNION;  	/* for occs only  	   */
"%token"	   |
"%term"		   return TERM_SPEC;
"%type"		   return TYPE;			/* for occs only  	   */
"%synch"	   return SYNCH;		/* for llama only 	   */
"%left"		   return LEFT;			/* for occs only  	   */
"%right"	   return RIGHT;		/* for occs only  	   */
"%nonassoc"	   return NONASSOC;		/* for occs only  	   */
"%prec"		   return PREC;			/* for occs only  	   */
"%start"	   return START;		/* for error messages only */
":"		   return COLON ;
"|"		   return OR    ;
";"		   return SEMI  ;
"["	   	   return START_OPT ;
"]"		   |
"]*"	   	   return END_OPT;

[^\x00-\s%\{}[\]()*:|;,<>]+	return NAME;
\x0d				; /* discard carriage return (\r) */
[\x00-\x0c\x0e-\s]		if( !Ignore ) return WHITESPACE;

%%
/*----------------------------------------------------------------------*/

PUBLIC  void  nows()  { Ignore = 1; }     /* Ignore white space, etc.       */
PUBLIC  void  ws  ()  { Ignore = 0; }     /* Don't ignore white space, etc. */

PUBLIC  int   start_action()    /* Return starting line number of most	*/
{				/* recently read ACTION block		*/
    return Start_line;
}
/*----------------------------------------------------------------------*/

PRIVATE void stripcr( src )       /* Remove all \r's (but not \n's) from src. */
char	*src;
{
    char	*dest;
    for( dest = src ; *src ; src++ )
	if( *src != '\r' )
	    *dest++ = *src;
    *dest = '\0';
}

   /*----------------------------------------------------------------------*/
#ifdef MAIN		    /* test routine, reads lexemes and prints them */

   int No_lines	= 0;
   char *Input_file_name;
   FILE *Output = stdout;
#include <stdarg.h>

   plex( lex )
   int lex;
   {
       switch( lex )
       {
       case ACTION:	   printf("ACTION (%s)\n",	   yytext); break;
       case CODE_BLOCK:	   printf("CODE_BLOCK (%s)\n",	   yytext); break;
       case COLON:	   printf("COLON (%s)\n",	   yytext); break;
       case END_OPT:	   printf("END_OPT (%s)\n",	   yytext); break;
       case FIELD:	   printf("FIELD (%s)\n",	   yytext); break;
       case LEFT:	   printf("LEFT (%s)\n",	   yytext); break;
       case NAME:	   printf("NAME (%s)\n",	   yytext); break;
       case NONASSOC:	   printf("NONASSOC (%s)\n",	   yytext); break;
       case OR:		   printf("OR (%s)\n",		   yytext); break;
       case OTHER:	   printf("OTHER (%s)\n",	   yytext); break;
       case PERCENT_UNION: printf("PERCENT_UNION (%s)\n",  yytext); break;
       case PREC:	   printf("PREC (%s)\n",	   yytext); break;
       case RIGHT:	   printf("RIGHT (%s)\n",	   yytext); break;
       case SEMI:	   printf("SEMI (%s)\n",	   yytext); break;
       case SEPARATOR:	   printf("SEPARATOR (%s)\n",	   yytext); break;
       case START:	   printf("START (%s)\n",	   yytext); break;
       case START_OPT:	   printf("START_OPT (%s)\n",	   yytext); break;
       case SYNCH:	   printf("SYNCH (%s)\n",	   yytext); break;
       case TERM_SPEC:	   printf("TERM_SPEC (%s)\n",	   yytext); break;
       case TYPE:	   printf("TYPE (%s)\n",	   yytext); break;
       case WHITESPACE:    printf("WHITESPACE (%s)\n",	   yytext); break;
       default:		   printf("*** unknown *** (%s)\n",yytext); break;
      }
   }

   void main( argc, argv )
   int argc;
   char	**argv;
   {
       int lex;
       if( argc == 1 )
       {
   	    while( lex = yylex() )
   	        plex( lex );
       }
       else
       {
   	if( ii_newfile( Input_file_name = argv[1] ) < 0 )
   	    perror( argv[1] );
   	else
   	    while( lex = yylex() )
  	    {
   	        plex( lex );
  	    }
       }
   }

   ANSI (PUBLIC void output( char *fmt,...) )
   UNIX (PUBLIC void output( fmt )	    )	/* The real versions of these */
   UNIX (char	*fmt;			    )	/* subroutines are in main.c. */
   {						/* These stubs are here for   */
       va_list   args;				/* debugging a standalone     */
       va_start( args,   fmt );			/* scanner.                   */
       vfprintf( Output, fmt, args );
       fflush  ( Output );
   }

   ANSI (PUBLIC void lerror( int status, char *fmt,...)	)
   UNIX (PUBLIC void lerror( status, fmt )		)
   UNIX (int	status;					)
   UNIX (char	*fmt;					)
   {
       va_list   args;
       va_start( args,   fmt );
       vfprintf( stderr, fmt, args );
       fflush  ( stderr );
       if( status == FATAL )
  	   exit(1);
   }
#endif

⌨️ 快捷键说明

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