📄 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 with or without * modification 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: /home/daffy/u0/vern/flex/RCS/scan.l,v 2.56 95/04/24 12:17:19 vern Exp $ */#include "flexdef.h"#include "parse.h"#define ACTION_ECHO add_action( yytext )#define ACTION_IFDEF(def, should_define) \ { \ if ( should_define ) \ action_define( def, 1 ); \ }#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;%}%option caseless nodefault outfile="scan.c" stack noyy_top_state%option nostdinit%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE%x FIRSTCCL CCL ACTION RECOVER COMMENT ACTION_STRING PERCENT_BRACE_ACTION%x OPTION LINEDIRWS [[:blank:]]+OPTWS [[:blank:]]*NOT_WS [^[:blank:]\n]NL \r?\nNAME ([[:alpha:]_][[:alnum:]_-]*)NOT_NAME [^[:alpha:]_*\n]+SCNAME {NAME}ESCSEQ (\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2}))FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ})CCL_CHAR ([^\\\n\]]|{ESCSEQ})CCL_EXPR ("[:"[[:alpha:]]+":]")LEXOPT [aceknopr]%% static int bracelevel, didadef, indented_code; static int doing_rule_action = false; static int option_sense; int doing_codeblock = false; int i; Char nmdef[MAXLINE], myesc();<INITIAL>{ ^{WS} indented_code = true; BEGIN(CODEBLOCK); ^"/*" ACTION_ECHO; yy_push_state( COMMENT ); ^#{OPTWS}line{WS} yy_push_state( LINEDIR ); ^"%s"{NAME}? return SCDECL; ^"%x"{NAME}? return XSCDECL; ^"%{".*{NL} { ++linenum; line_directive_out( (FILE *) 0, 1 ); indented_code = false; BEGIN(CODEBLOCK); } {WS} /* discard */ ^"%%".* { sectnum = 2; bracelevel = 0; mark_defs1(); line_directive_out( (FILE *) 0, 1 ); BEGIN(SECT2PROLOG); return SECTEND; } ^"%pointer".*{NL} yytext_is_array = false; ++linenum; ^"%array".*{NL} yytext_is_array = true; ++linenum; ^"%option" BEGIN(OPTION); return OPTION_OP; ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} ++linenum; /* ignore */ ^"%"{LEXOPT}{WS}.*{NL} ++linenum; /* ignore */ ^"%"[^sxaceknopr{}].* synerr( _( "unrecognized '%' directive" ) ); ^{NAME} { strcpy( nmstr, yytext ); didadef = false; BEGIN(PICKUPDEF); } {SCNAME} RETURNNAME; ^{OPTWS}{NL} ++linenum; /* allows blank lines in section 1 */ {OPTWS}{NL} ACTION_ECHO; ++linenum; /* maybe end of comment line */}<COMMENT>{ "*/" ACTION_ECHO; yy_pop_state(); "*" ACTION_ECHO; [^*\n]+ ACTION_ECHO; [^*\n]*{NL} ++linenum; ACTION_ECHO;}<LINEDIR>{ \n yy_pop_state(); [[:digit:]]+ linenum = myctoi( yytext ); \"[^"\n]*\" { flex_free( (void *) infilename ); infilename = copy_string( yytext + 1 ); infilename[strlen( infilename ) - 1] = '\0'; } . /* ignore spurious characters */}<CODEBLOCK>{ ^"%}".*{NL} ++linenum; BEGIN(INITIAL); {NAME}|{NOT_NAME}|. ACTION_ECHO; {NL} { ++linenum; ACTION_ECHO; if ( indented_code ) BEGIN(INITIAL); }}<PICKUPDEF>{ {WS} /* separates name and definition */ {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; } {NL} { if ( ! didadef ) synerr( _( "incomplete name definition" ) ); BEGIN(INITIAL); ++linenum; }}<OPTION>{ {NL} ++linenum; BEGIN(INITIAL); {WS} option_sense = true; "=" return '='; no option_sense = ! option_sense; 7bit csize = option_sense ? 128 : 256; 8bit csize = option_sense ? 256 : 128; align long_align = option_sense; always-interactive { action_define( "YY_ALWAYS_INTERACTIVE", option_sense ); } array yytext_is_array = option_sense; backup backing_up_report = option_sense; batch interactive = ! option_sense; "c++" C_plus_plus = option_sense; caseful|case-sensitive caseins = ! option_sense; caseless|case-insensitive caseins = option_sense; debug ddebug = option_sense; default spprdflt = ! option_sense; ecs useecs = option_sense; fast { useecs = usemecs = false; use_read = fullspd = true; } full { useecs = usemecs = false; use_read = fulltbl = true; } input ACTION_IFDEF("YY_NO_INPUT", ! option_sense); interactive interactive = option_sense; lex-compat lex_compat = option_sense; main { action_define( "YY_MAIN", option_sense ); do_yywrap = ! option_sense; } meta-ecs usemecs = option_sense; never-interactive { action_define( "YY_NEVER_INTERACTIVE", option_sense ); } perf-report performance_report += option_sense ? 1 : -1; pointer yytext_is_array = ! option_sense; read use_read = option_sense; reject reject_really_used = option_sense; stack action_define( "YY_STACK_USED", option_sense ); stdinit do_stdinit = option_sense; stdout use_stdout = option_sense; unput ACTION_IFDEF("YY_NO_UNPUT", ! option_sense); verbose printstats = option_sense; warn nowarn = ! option_sense; yylineno do_yylineno = option_sense; yymore yymore_really_used = option_sense; yywrap do_yywrap = option_sense; yy_push_state ACTION_IFDEF("YY_NO_PUSH_STATE", ! option_sense); yy_pop_state ACTION_IFDEF("YY_NO_POP_STATE", ! option_sense); yy_top_state ACTION_IFDEF("YY_NO_TOP_STATE", ! option_sense); yy_scan_buffer ACTION_IFDEF("YY_NO_SCAN_BUFFER", ! option_sense); yy_scan_bytes ACTION_IFDEF("YY_NO_SCAN_BYTES", ! option_sense); yy_scan_string ACTION_IFDEF("YY_NO_SCAN_STRING", ! option_sense); outfile return OPT_OUTFILE; prefix return OPT_PREFIX; yyclass return OPT_YYCLASS; \"[^"\n]*\" { strcpy( nmstr, yytext + 1 ); nmstr[strlen( nmstr ) - 1] = '\0'; return NAME; } (([a-mo-z]|n[a-np-z])[[:alpha:]\-+]*)|. { format_synerr( _( "unrecognized %%option: %s" ), yytext ); BEGIN(RECOVER); }}<RECOVER>.*{NL} ++linenum; BEGIN(INITIAL);<SECT2PROLOG>{ ^"%{".* ++bracelevel; yyless( 2 ); /* eat only %{ */ ^"%}".* --bracelevel; yyless( 2 ); /* eat only %} */ ^{WS}.* ACTION_ECHO; /* indented code in prolog */ ^{NOT_WS}.* { /* non-indented code */ if ( bracelevel <= 0 ) { /* not in %{ ... %} */ yyless( 0 ); /* put it all back */ yy_set_bol( 1 ); mark_prolog(); BEGIN(SECT2); } else ACTION_ECHO; } .* ACTION_ECHO; {NL} ++linenum; ACTION_ECHO; <<EOF>> { mark_prolog(); sectnum = 0; yyterminate(); /* to stop the parser */ }}<SECT2>{ ^{OPTWS}{NL} ++linenum; /* allow blank lines in section 2 */ ^{OPTWS}"%{" { indented_code = false; doing_codeblock = true; bracelevel = 1; BEGIN(PERCENT_BRACE_ACTION); } ^{OPTWS}"<" BEGIN(SC); return '<'; ^{OPTWS}"^" return '^'; \" BEGIN(QUOTE); return '"'; "{"/[[:digit:]] BEGIN(NUM); return '{'; "$"/([[:blank:]]|{NL}) return '$'; {WS}"%{" { bracelevel = 1; BEGIN(PERCENT_BRACE_ACTION); if ( in_rule ) { doing_rule_action = true; in_rule = false; return '\n'; } } {WS}"|".*{NL} continued_action = true; ++linenum; return '\n'; ^{WS}"/*" { yyless( yyleng - 2 ); /* put back '/', '*' */ bracelevel = 0; continued_action = false; BEGIN(ACTION); } ^{WS} /* allow indented rules */ {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); if ( in_rule ) { doing_rule_action = true; in_rule = false; return '\n'; } } {OPTWS}{NL} { bracelevel = 0; continued_action = false; BEGIN(ACTION); unput( '\n' ); /* so <ACTION> sees it */ if ( in_rule ) { doing_rule_action = true; in_rule = false; return '\n'; } } ^{OPTWS}"<<EOF>>" | "<<EOF>>" return EOF_OP; ^"%%".* { sectnum = 3; BEGIN(SECT3); yyterminate(); /* to stop the parser */ } "["({FIRST_CCL_CHAR}|{CCL_EXPR})({CCL_CHAR}|{CCL_EXPR})* { int cclval; strcpy( nmstr, yytext ); /* Check to see if we've already encountered this * ccl. */ if ( (cclval = ccllookup( (Char *) nmstr )) != 0 ) { 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 '['; } } "{"{NAME}"}" { register Char *nmdefptr; Char *ndlookup(); strcpy( nmstr, yytext + 1 ); nmstr[yyleng - 2] = '\0'; /* chop trailing brace */ if ( (nmdefptr = ndlookup( nmstr )) == 0 ) 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('('); } } } [/|*+?.(){}] return (unsigned char) yytext[0]; . RETURNCHAR;}<SC>{ [,*] return (unsigned char) yytext[0]; ">" BEGIN(SECT2); return '>'; ">"/^ BEGIN(CARETISBOL); return '>'; {SCNAME} RETURNNAME; . { format_synerr( _( "bad <start condition>: %s" ), yytext ); }}<CARETISBOL>"^" BEGIN(SECT2); return '^';<QUOTE>{ [^"\n] RETURNCHAR; \" BEGIN(SECT2); return '"'; {NL} { synerr( _( "missing quote" ) ); BEGIN(SECT2); ++linenum; return '"'; }}<FIRSTCCL>{ "^"/[^-\]\n] BEGIN(CCL); return '^'; "^"/("-"|"]") return '^'; . BEGIN(CCL); RETURNCHAR;}<CCL>{ -/[^\]\n] return '-'; [^\]\n] RETURNCHAR; "]" BEGIN(SECT2); return ']'; .|{NL} { synerr( _( "bad character class" ) ); BEGIN(SECT2); return ']'; }}<FIRSTCCL,CCL>{ "[:alnum:]" BEGIN(CCL); return CCE_ALNUM; "[:alpha:]" BEGIN(CCL); return CCE_ALPHA; "[:blank:]" BEGIN(CCL); return CCE_BLANK; "[:cntrl:]" BEGIN(CCL); return CCE_CNTRL; "[:digit:]" BEGIN(CCL); return CCE_DIGIT; "[:graph:]" BEGIN(CCL); return CCE_GRAPH; "[:lower:]" BEGIN(CCL); return CCE_LOWER; "[:print:]" BEGIN(CCL); return CCE_PRINT; "[:punct:]" BEGIN(CCL); return CCE_PUNCT; "[:space:]" BEGIN(CCL); return CCE_SPACE; "[:upper:]" BEGIN(CCL); return CCE_UPPER; "[:xdigit:]" BEGIN(CCL); return CCE_XDIGIT; {CCL_EXPR} { format_synerr( _( "bad character class expression: %s" ), yytext ); BEGIN(CCL); return CCE_ALNUM; }}<NUM>{ [[:digit:]]+ { yylval = myctoi( yytext ); return NUMBER; } "," return ','; "}" BEGIN(SECT2); return '}'; . { synerr( _( "bad character inside {}'s" ) ); BEGIN(SECT2); return '}'; } {NL} { synerr( _( "missing }" ) ); BEGIN(SECT2); ++linenum; return '}'; }}<PERCENT_BRACE_ACTION>{ {OPTWS}"%}".* bracelevel = 0; <ACTION>"/*" ACTION_ECHO; yy_push_state( COMMENT ); <CODEBLOCK,ACTION>{ "reject" { ACTION_ECHO; CHECK_REJECT(yytext); } "yymore" { ACTION_ECHO; CHECK_YYMORE(yytext); } } {NAME}|{NOT_NAME}|. ACTION_ECHO; {NL} { ++linenum; ACTION_ECHO; if ( bracelevel == 0 || (doing_codeblock && indented_code) ) { if ( doing_rule_action ) add_action( "\tYY_BREAK\n" ); doing_rule_action = doing_codeblock = false; BEGIN(SECT2); } }} /* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */<ACTION>{ "{" ACTION_ECHO; ++bracelevel; "}" ACTION_ECHO; --bracelevel; [^[:alpha:]_{}"'/\n]+ ACTION_ECHO; {NAME} ACTION_ECHO; "'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */ \" ACTION_ECHO; BEGIN(ACTION_STRING); {NL} { ++linenum; ACTION_ECHO; if ( bracelevel == 0 ) { if ( doing_rule_action ) add_action( "\tYY_BREAK\n" ); doing_rule_action = false; BEGIN(SECT2); } } . ACTION_ECHO;}<ACTION_STRING>{ [^"\\\n]+ ACTION_ECHO; \\. ACTION_ECHO; {NL} ++linenum; ACTION_ECHO; \" ACTION_ECHO; BEGIN(ACTION); . ACTION_ECHO;}<COMMENT,ACTION,ACTION_STRING><<EOF>> { synerr( _( "EOF encountered inside an action" ) ); yyterminate(); }<SECT2,QUOTE,FIRSTCCL,CCL>{ESCSEQ} { yylval = myesc( (Char *) yytext ); if ( YY_START == FIRSTCCL ) BEGIN(CCL); return CHAR; }<SECT3>{ .*(\n?) ECHO; <<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 && strcmp( file, "-" ) ) { infilename = copy_string( file ); yyin = fopen( infilename, "r" ); if ( yyin == NULL ) lerrsf( _( "can't open %s" ), file ); } else { yyin = stdin; infilename = copy_string( "<stdin>" ); } linenum = 1; }/* Wrapper routines for accessing the scanner's malloc routines. */void *flex_alloc( size )size_t size; { return (void *) malloc( size ); }void *flex_realloc( ptr, size )void *ptr;size_t size; { return (void *) realloc( ptr, size ); }void flex_free( ptr )void *ptr; { if ( ptr ) free( ptr ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -