📄 scan.l
字号:
/* scan.l - scanner for flex input */%{/*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Vern Paxson. * * The United States Government has rights in this work pursuant * to contract no. DE-AC03-76SF00098 between the United States * Department of Energy and the University of California. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *//* $Header: scan.l,v 1.2 94/01/04 14:33:09 vern Exp $ */#include "flexdef.h"#include "parse.h"#define ACTION_ECHO add_action( yytext )#define MARK_END_OF_PROLOG mark_prolog();#define YY_DECL \ int flexscan()#define RETURNCHAR \ yylval = (unsigned char) yytext[0]; \ return CHAR;#define RETURNNAME \ strcpy( nmstr, yytext ); \ return NAME;#define PUT_BACK_STRING(str, start) \ for ( i = strlen( str ) - 1; i >= start; --i ) \ unput((str)[i])#define CHECK_REJECT(str) \ if ( all_upper( str ) ) \ reject = true;#define CHECK_YYMORE(str) \ if ( all_lower( str ) ) \ yymore_used = true;%}%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE%x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT ACTION_COMMENT%x ACTION_STRING PERCENT_BRACE_ACTION USED_LIST CODEBLOCK_2WS [ \t]+OPTWS [ \t]*NOT_WS [^ \t\n]NL (\n|\r\n|\n\r)NAME ([a-z_][a-z_0-9-]*)NOT_NAME [^a-z_*\n]+SCNAME {NAME}ESCSEQ (\\([^\n]|[0-9]{1,3}|x[0-9a-f]{1,2}))FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ})CCL_CHAR ([^\\\n\]]|{ESCSEQ})%% static int bracelevel, didadef, indented_code, checking_used; int doing_codeblock = false; int i; Char nmdef[MAXLINE], myesc();^{WS} indented_code = true; BEGIN(CODEBLOCK);^"/*" ACTION_ECHO; BEGIN(C_COMMENT);^"%s"{NAME}? return SCDECL;^"%x"{NAME}? return XSCDECL;^"%{".*{NL} { ++linenum; line_directive_out( (FILE *) 0 ); indented_code = false; BEGIN(CODEBLOCK); }{WS} return WHITESPACE;^"%%".* { sectnum = 2; bracelevel = 0; mark_defs1(); line_directive_out( (FILE *) 0 ); BEGIN(SECT2PROLOG); return SECTEND; }^"%pointer".*{NL} { if ( lex_compat ) warn( "%pointer incompatible with -l option" ); else yytext_is_array = false; ++linenum; }^"%array".*{NL} { if ( C_plus_plus ) warn( "%array incompatible with -+ option" ); else yytext_is_array = true; ++linenum; }^"%used" { warn( "%used/%unused have been deprecated" ); checking_used = REALLY_USED; BEGIN(USED_LIST); }^"%unused" { warn( "%used/%unused have been deprecated" ); checking_used = REALLY_NOT_USED; BEGIN(USED_LIST); }^"%"[aceknopr]{OPTWS}[0-9]*{OPTWS}{NL} ++linenum; /* ignore */^"%"[^sxanpekotcru{}].* synerr( "unrecognized '%' directive" );^{NAME} { strcpy( nmstr, yytext ); didadef = false; BEGIN(PICKUPDEF); }{SCNAME} RETURNNAME;^{OPTWS}{NL} ++linenum; /* allows blank lines in section 1 */{OPTWS}{NL} ++linenum; return '\n';<C_COMMENT>"*/" ACTION_ECHO; BEGIN(INITIAL);<C_COMMENT>"*/".*{NL} ++linenum; ACTION_ECHO; BEGIN(INITIAL);<C_COMMENT>[^*\n]+ ACTION_ECHO;<C_COMMENT>"*" ACTION_ECHO;<C_COMMENT>{NL} ++linenum; ACTION_ECHO;<CODEBLOCK>^"%}".*{NL} ++linenum; BEGIN(INITIAL);<CODEBLOCK>"reject" ACTION_ECHO; CHECK_REJECT(yytext);<CODEBLOCK>"yymore" ACTION_ECHO; CHECK_YYMORE(yytext);<CODEBLOCK>{NAME}|{NOT_NAME}|. ACTION_ECHO;<CODEBLOCK>{NL} { ++linenum; ACTION_ECHO; if ( indented_code ) BEGIN(INITIAL); }<PICKUPDEF>{WS} /* separates name and definition */<PICKUPDEF>{NOT_WS}.* { strcpy( (char *) nmdef, yytext ); /* Skip trailing whitespace. */ for ( i = strlen( (char *) nmdef ) - 1; i >= 0 && (nmdef[i] == ' ' || nmdef[i] == '\t'); --i ) ; nmdef[i + 1] = '\0'; ndinstal( nmstr, nmdef ); didadef = true; }<PICKUPDEF>{NL} { if ( ! didadef ) synerr( "incomplete name definition" ); BEGIN(INITIAL); ++linenum; }<RECOVER>.*{NL} ++linenum; BEGIN(INITIAL); RETURNNAME;<USED_LIST>{NL} ++linenum; BEGIN(INITIAL);<USED_LIST>{WS}<USED_LIST>"reject" { if ( all_upper( yytext ) ) reject_really_used = checking_used; else synerr( "unrecognized %used/%unused construct" ); }<USED_LIST>"yymore" { if ( all_lower( yytext ) ) yymore_really_used = checking_used; else synerr( "unrecognized %used/%unused construct" ); }<USED_LIST>{NOT_WS}+ synerr( "unrecognized %used/%unused construct" );<SECT2PROLOG>^"%{".* ++bracelevel; yyless( 2 ); /* eat only %{ */<SECT2PROLOG>^"%}".* --bracelevel; yyless( 2 ); /* eat only %} */<SECT2PROLOG>^{WS}.* ACTION_ECHO; /* indented code in prolog */<SECT2PROLOG>^{NOT_WS}.* { /* non-indented code */ if ( bracelevel <= 0 ) { /* not in %{ ... %} */ yyless( 0 ); /* put it all back */ mark_prolog(); BEGIN(SECT2); } else ACTION_ECHO; }<SECT2PROLOG>.* ACTION_ECHO;<SECT2PROLOG>{NL} ++linenum; ACTION_ECHO;<SECT2PROLOG><<EOF>> { mark_prolog(); sectnum = 0; yyterminate(); /* to stop the parser */ }<SECT2>^{OPTWS}{NL} ++linenum; /* allow blank lines in section 2 */<SECT2>^({WS}|"%{") { indented_code = (yytext[0] != '%'); doing_codeblock = true; bracelevel = 1; if ( indented_code ) ACTION_ECHO; BEGIN(CODEBLOCK_2); }<SECT2>^"<" BEGIN(SC); return '<';<SECT2>^"^" return '^';<SECT2>\" BEGIN(QUOTE); return '"';<SECT2>"{"/[0-9] BEGIN(NUM); return '{';<SECT2>"{"[^0-9\n][^}\n]* BEGIN(BRACEERROR);<SECT2>"$"/([ \t]|{NL}) return '$';<SECT2>{WS}"%{" { bracelevel = 1; BEGIN(PERCENT_BRACE_ACTION); return '\n'; }<SECT2>{WS}"|".*{NL} continued_action = true; ++linenum; return '\n';<SECT2>{WS} { /* This rule is separate from the one below because * otherwise we get variable trailing context, so * we can't build the scanner using -{f,F}. */ bracelevel = 0; continued_action = false; BEGIN(ACTION); return '\n'; }<SECT2>{OPTWS}{NL} { bracelevel = 0; continued_action = false; BEGIN(ACTION); unput( '\n' ); /* so <ACTION> sees it */ return '\n'; }<SECT2>"<<EOF>>" return EOF_OP;<SECT2>^"%%".* { sectnum = 3; BEGIN(SECT3); yyterminate(); /* to stop the parser */ }<SECT2>"["{FIRST_CCL_CHAR}{CCL_CHAR}* { int cclval; strcpy( nmstr, yytext ); /* Check to see if we've already encountered this * ccl. */ if ( (cclval = ccllookup( (Char *) nmstr )) ) { if ( input() != ']' ) synerr( "bad character class" ); yylval = cclval; ++cclreuse; return PREVCCL; } else { /* We fudge a bit. We know that this ccl will * soon be numbered as lastccl + 1 by cclinit. */ cclinstal( (Char *) nmstr, lastccl + 1 ); /* Push back everything but the leading bracket * so the ccl can be rescanned. */ yyless( 1 ); BEGIN(FIRSTCCL); return '['; } }<SECT2>"{"{NAME}"}" { register Char *nmdefptr; Char *ndlookup(); strcpy( nmstr, yytext + 1 ); nmstr[yyleng - 2] = '\0'; /* chop trailing brace */ if ( ! (nmdefptr = ndlookup( nmstr )) ) format_synerr( "undefined definition {%s}", nmstr ); else { /* push back name surrounded by ()'s */ int len = strlen( (char *) nmdefptr ); if ( lex_compat || nmdefptr[0] == '^' || (len > 0 && nmdefptr[len - 1] == '$') ) { /* don't use ()'s after all */ PUT_BACK_STRING((char *) nmdefptr, 0); if ( nmdefptr[0] == '^' ) BEGIN(CARETISBOL); } else { unput(')'); PUT_BACK_STRING((char *) nmdefptr, 0); unput('('); } } }<SECT2>[/|*+?.()] return (unsigned char) yytext[0];<SECT2>. RETURNCHAR;<SC>[,*] return (unsigned char) yytext[0];<SC>">" BEGIN(SECT2); return '>';<SC>">"/^ BEGIN(CARETISBOL); return '>';<SC>{SCNAME} RETURNNAME;<SC>. { format_synerr( "bad <start condition>: %s", yytext ); }<CARETISBOL>"^" BEGIN(SECT2); return '^';<QUOTE>[^"\n] RETURNCHAR;<QUOTE>\" BEGIN(SECT2); return '"';<QUOTE>{NL} { synerr( "missing quote" ); BEGIN(SECT2); ++linenum; return '"'; }<FIRSTCCL>"^"/[^-\]\n] BEGIN(CCL); return '^';<FIRSTCCL>"^"/("-"|"]") return '^';<FIRSTCCL>. BEGIN(CCL); RETURNCHAR;<CCL>-/[^\]\n] return '-';<CCL>[^\]\n] RETURNCHAR;<CCL>"]" BEGIN(SECT2); return ']';<CCL>.|{NL} { synerr( "bad character class" ); BEGIN(SECT2); return ']'; }<NUM>[0-9]+ { yylval = myctoi( yytext ); return NUMBER; }<NUM>"," return ',';<NUM>"}" BEGIN(SECT2); return '}';<NUM>. { synerr( "bad character inside {}'s" ); BEGIN(SECT2); return '}'; }<NUM>{NL} { synerr( "missing }" ); BEGIN(SECT2); ++linenum; return '}'; }<BRACEERROR>"}" synerr( "bad name in {}'s" ); BEGIN(SECT2);<BRACEERROR>{NL} synerr( "missing }" ); ++linenum; BEGIN(SECT2);<CODEBLOCK_2>"/*" ACTION_ECHO; BEGIN(ACTION_COMMENT);<PERCENT_BRACE_ACTION,CODEBLOCK_2>{OPTWS}"%}".* bracelevel = 0;<PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"reject" { ACTION_ECHO; CHECK_REJECT(yytext); }<PERCENT_BRACE_ACTION,CODEBLOCK_2,ACTION>"yymore" { ACTION_ECHO; CHECK_YYMORE(yytext); }<PERCENT_BRACE_ACTION,CODEBLOCK_2>{NAME}|{NOT_NAME}|. ACTION_ECHO;<PERCENT_BRACE_ACTION,CODEBLOCK_2>{NL} { ++linenum; ACTION_ECHO; if ( bracelevel == 0 || (doing_codeblock && indented_code) ) { if ( ! doing_codeblock ) add_action( "\tYY_BREAK\n" ); doing_codeblock = false; BEGIN(SECT2); } } /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */<ACTION>"{" ACTION_ECHO; ++bracelevel;<ACTION>"}" ACTION_ECHO; --bracelevel;<ACTION>[^a-z_{}"'/\n]+ ACTION_ECHO;<ACTION>{NAME} ACTION_ECHO;<ACTION>"/*" ACTION_ECHO; BEGIN(ACTION_COMMENT);<ACTION>"'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */<ACTION>\" ACTION_ECHO; BEGIN(ACTION_STRING);<ACTION>{NL} { ++linenum; ACTION_ECHO; if ( bracelevel == 0 ) { add_action( "\tYY_BREAK\n" ); BEGIN(SECT2); } }<ACTION>. ACTION_ECHO;<ACTION_COMMENT>"*/" { ACTION_ECHO; if ( doing_codeblock ) BEGIN(CODEBLOCK_2); else BEGIN(ACTION); }<ACTION_COMMENT>"*" ACTION_ECHO;<ACTION_COMMENT>[^*\n]+ ACTION_ECHO;<ACTION_COMMENT>[^*\n]*{NL} ++linenum; ACTION_ECHO;<ACTION_STRING>[^"\\\n]+ ACTION_ECHO;<ACTION_STRING>\\. ACTION_ECHO;<ACTION_STRING>{NL} ++linenum; ACTION_ECHO;<ACTION_STRING>\" ACTION_ECHO; BEGIN(ACTION);<ACTION_STRING>. ACTION_ECHO;<ACTION,ACTION_COMMENT,ACTION_STRING><<EOF>> { synerr( "EOF encountered inside an action" ); yyterminate(); }<SECT2,QUOTE,CCL>{ESCSEQ} { yylval = myesc( (Char *) yytext ); return CHAR; }<FIRSTCCL>{ESCSEQ} { yylval = myesc( (Char *) yytext ); BEGIN(CCL); return CHAR; }<SECT3>.*(\n?) ECHO;<SECT3><<EOF>> sectnum = 0; yyterminate();<*>.|\n format_synerr( "bad character: %s", yytext );%%int yywrap() { if ( --num_input_files > 0 ) { set_input_file( *++input_files ); return 0; } else return 1; }/* set_input_file - open the given file (if NULL, stdin) for scanning */void set_input_file( file )char *file; { if ( file ) { infilename = file; yyin = fopen( infilename, "r" ); if ( yyin == NULL ) lerrsf( "can't open %s", file ); } else { yyin = stdin; infilename = "<stdin>"; } }/* Wrapper routines for accessing the scanner's malloc routines. */void *flex_alloc( size )unsigned int size; { return yy_flex_alloc( size ); }void *flex_realloc( ptr, size )void *ptr;unsigned int size; { return yy_flex_realloc( ptr, size ); }void flex_free( ptr )void *ptr; { yy_flex_free( ptr ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -