/* * Copyright (c) 1997 Ross Cunniff * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ %{ extern void yyerror(char *); extern int yylex(void); %} /* Multicharacter reserved words */ %token T_ASSERT T_BREAK T_CASE T_CATCH T_CLASS %token T_CONST T_CONTINUE T_DEFAULT T_DO T_ELSE %token T_EXTERN T_FOR T_FORALL T_IF T_MATCH %token T_NAMESPACE T_NEW T_OPERATOR T_PROC %token T_PROTECTED T_PUBLIC T_RETURN T_SWITCH T_THROW %token T_TRY T_USING T_VAR T_WHILE T_WITH %token T_STATIC T_LOOPBASE %token T_FOREACH /* Preprocessor symbols */ %token T_DEFINE T_INCLUDE /* Other multicharacter tokens */ %token T_NAME T_INTCON T_FLOATCON T_STRING T_CHARCON T_MATCH_ARG %token T_LCHARCON T_LSTRING /* Punctuation */ %token T_SEMI T_COMMA T_EQUALS T_LBRACE T_RBRACE T_LPAR T_RPAR T_OR T_XOR %token T_AND T_LT T_GT T_PLUS T_MINUS T_STAR T_SLASH T_PCT T_NOT T_BANG %token T_DOT T_LBRAK T_RBRAK T_COLON T_AT T_QUEST T_STARSTAR T_BACKTICK /* Two-char punctuation */ %token T_CONCAT T_EQEQ T_NOTEQ T_LE T_GE T_PLUSEQ T_MINUSEQ T_STAREQ %token T_SLASHEQ T_PCTEQ T_ANDEQ T_OREQ T_XOREQ T_LSHIFT T_RSHIFT %token T_ANDAND T_OROR T_PLUSPLUS T_MINUSMINUS T_EQGT T_QUEST_EQ %token T_MATCHES T_MATCH_COUNT T_COLON_COLON T_HASH_EQ T_AT_AT %token T_HASH_LBRAK T_HASH_LPAR T_QUEST_QUEST T_COLON_EQUALS %token T_HASH_LBRACE /* Three-char punctuation */ %token T_LSHIFTEQ T_RSHIFTEQ T_LLL T_RRR T_DOTDOTDOT /* "Reverse" punctuation */ %token T_OR_R T_XOR_R T_AND_R T_LT_R T_GT_R T_PLUS_R T_MINUS_R T_BANG_MINUS %token T_STAR_R T_SLASH_R T_PCT_R T_POW_R T_EQEQ_R T_NOTEQ_R T_LE_R T_GE_R %token T_LSHIFT_R T_RSHIFT_R T_EQGT_R T_MATCHES_R /* End-of-file marker */ %token T_EOF /* Handle the dangling else shift/reduce conflict */ %nonassoc T_THEN %nonassoc T_ELSE /* Handle the dangling :: shift/reduce conflict */ %nonassoc T_NAME %nonassoc T_COLON_COLON %% program : prog T_EOF { return 0; } ; prog : decl | prog decl ; decl : class_decl | var_decl | proc_decl | const_decl | include | using | define | public_decl | default_public | extern_decl | obj_decl | T_NAMESPACE T_NAME T_LBRACE prog T_RBRACE ; class_decl : T_CLASS qual_name proplist | T_CLASS qual_name T_LPAR qual_names T_RPAR proplist | T_CLASS qual_names T_SEMI ; proplist : T_LBRACE props T_RBRACE ; props : /* NOTHING */ | props prop ; prop : T_PUBLIC oneprop | T_PROTECTED oneprop | oneprop ; oneprop : var_decl | const_decl | proc_decl | T_OPERATOR oper_decl ; var_decl : T_VAR vars T_SEMI | T_STATIC vars T_SEMI ; vars : var | vars T_COMMA var ; var : qual_name | qual_name T_EQUALS expr | qual_name T_COLON type | qual_name T_COLON type T_EQUALS expr ; type : T_NAME | T_NAME T_LBRAK exprlist T_RBRAK | T_NAME T_LBRAK T_STAR T_RBRAK ; const_decl : T_CONST consts T_SEMI ; consts : name_init | consts T_COMMA name_init ; name_init : qual_name T_EQUALS expr ; oper_decl : operator no_name_proc ; operator : T_OR | T_XOR | T_AND | T_LT | T_GT | T_PLUS | T_MINUS | T_STAR | T_SLASH | T_STARSTAR | T_PCT | T_NOT | T_CONCAT | T_EQEQ | T_NOTEQ | T_LE | T_GE | T_LSHIFT | T_RSHIFT | T_LBRACE T_RBRACE | T_LBRAK T_RBRAK | T_LBRAK T_EQUALS T_RBRAK | T_HASH_LBRAK T_RBRAK | T_HASH_LBRAK T_EQUALS T_RBRAK | T_LPAR T_RPAR | T_EQGT | T_MATCHES | T_PLUSPLUS | T_MINUSMINUS | T_OR_R | T_XOR_R | T_AND_R | T_LT_R | T_GT_R | T_PLUS_R | T_MINUS_R | T_BANG_MINUS | T_STAR_R | T_SLASH_R | T_PCT_R | T_POW_R | T_EQEQ_R | T_NOTEQ_R | T_LE_R | T_GE_R | T_LSHIFT_R | T_RSHIFT_R | T_EQGT_R | T_MATCHES_R | T_COLON_EQUALS ; include : T_INCLUDE T_STRING ; using : T_USING using_decls T_SEMI ; using_decls : one_use | using_decls T_COMMA one_use ; one_use : T_NAMESPACE T_NAME | T_EXTERN T_STRING | qual_name ; define : T_DEFINE T_NAME T_LPAR names T_RPAR T_LBRACE defn T_RBRACE | T_DEFINE T_NAME T_LPAR T_RPAR T_LBRACE defn T_RBRACE ; defn : /* NOTHING */ | defn token | defn T_LPAR defn T_RPAR | defn T_LBRACE defn T_RBRACE | defn T_LBRAK defn T_RBRAK | defn T_HASH_LBRAK defn T_RBRAK | defn T_HASH_LPAR defn T_RBRAK ; token : T_CLASS | T_VAR | T_CONST | T_PUBLIC | T_PROC | T_IF | T_ELSE | T_WHILE | T_BREAK | T_RETURN | T_INCLUDE | T_SWITCH | T_CASE | T_DEFAULT | T_FOR | T_DO | T_FORALL | T_CONTINUE | T_NEW | T_OPERATOR | T_PROTECTED | T_TRY | T_CATCH | T_THROW | T_ASSERT | T_DEFINE | T_NAME | T_INTCON | T_FLOATCON | T_STRING | T_CHARCON | T_LSTRING | T_LCHARCON | T_SEMI | T_COMMA | T_EQUALS | T_OR | T_XOR | T_AND | T_LT | T_GT | T_PLUS | T_MINUS | T_STAR | T_SLASH | T_STARSTAR | T_PCT | T_NOT | T_BANG | T_DOT | T_COLON | T_AT | T_CONCAT | T_EQEQ | T_NOTEQ | T_LE | T_GE | T_PLUSEQ | T_MINUSEQ | T_STAREQ | T_SLASHEQ | T_PCTEQ | T_ANDEQ | T_OREQ | T_XOREQ | T_LSHIFT | T_RSHIFT | T_ANDAND | T_OROR | T_PLUSPLUS | T_MINUSMINUS | T_EQGT | T_QUEST_EQ | T_LSHIFTEQ | T_RSHIFTEQ | T_MATCH | T_MATCHES | T_MATCH_ARG | T_MATCH_COUNT | T_USING | T_NAMESPACE | T_QUEST | T_COLON_COLON | T_WITH | T_EXTERN | T_HASH_EQ | T_AT_AT | T_QUEST_QUEST | T_OR_R | T_XOR_R | T_AND_R | T_LT_R | T_GT_R | T_PLUS_R | T_MINUS_R | T_BANG_MINUS | T_STAR_R | T_SLASH_R | T_PCT_R | T_POW_R | T_EQEQ_R | T_NOTEQ_R | T_LE_R | T_GE_R | T_LSHIFT_R | T_RSHIFT_R | T_EQGT_R | T_MATCHES_R | T_COLON_EQUALS ; public_decl : T_PUBLIC names T_SEMI ; default_public : T_DEFAULT T_PUBLIC consts T_SEMI ; extern_decl : T_EXTERN names T_SEMI ; names : T_NAME | names T_COMMA T_NAME ; qual_names : qual_name | qual_names T_COMMA qual_name ; obj_decl : obj_decl_list T_SEMI | obj_decl_props ; obj_decl_list : obj_decl_noprop | obj_decl T_COMMA obj_decl_noprop ; obj_decl_noprop : qual_name qual_name | qual_name qual_name T_LPAR exprs T_RPAR ; obj_decl_props : qual_name qual_name obj_proplist | qual_name qual_name T_LPAR exprs T_RPAR obj_proplist | T_DOTDOTDOT qual_name obj_proplist ; obj_proplist : T_LBRACE obj_props T_RBRACE | T_LBRACE obj_props T_DOTDOTDOT T_RBRACE ; obj_props : /* NOTHING */ | obj_props prop_init ; prop_init : T_NAME T_EQUALS expr ; proc_decl : T_PROC qual_name T_LPAR args T_RPAR proc_body | T_PROC qual_name T_LPAR T_RPAR proc_body | T_PROC T_STRING qual_name T_LPAR args T_RPAR proc_body | T_PROC T_STRING qual_name T_LPAR T_RPAR proc_body | T_PROC qual_names T_SEMI ; args : T_NAME | T_NAME T_COLON type | args T_COMMA T_NAME | args T_COMMA T_NAME T_COLON type ; no_name_proc : T_LPAR names T_RPAR proc_body | T_LPAR T_RPAR proc_body ; proc_body : T_LBRACE stmts T_RBRACE | T_COLON type T_LBRACE stmts T_RBRACE ; stmts : /* NOTHING */ | stmt stmts ; stmt : assign T_SEMI | call T_SEMI | ifstmt | whilestmt | dostmt T_SEMI | forstmt | forallstmt | switchstmt | matchstmt | withstmt | returnstmt T_SEMI | assertstmt T_SEMI | trystmt | throwstmt T_SEMI | breakstmt T_SEMI | continuestmt T_SEMI | var_decl | const_decl | using | printstmt T_SEMI ; assign : lhs T_EQUALS expr | lhs T_PLUSEQ expr | lhs T_MINUSEQ expr | lhs T_STAREQ expr | lhs T_SLASHEQ expr | lhs T_PCTEQ expr | lhs T_ANDEQ expr | lhs T_OREQ expr | lhs T_XOREQ expr | lhs T_LSHIFTEQ expr | lhs T_RSHIFTEQ expr | lhs T_PLUSPLUS | lhs T_MINUSMINUS ; call : lhs T_LPAR exprs T_RPAR | lhs T_HASH_LPAR exprs T_RPAR ; lhs : qual_name | lhs T_DOT T_NAME | lhs T_DOT T_LPAR expr T_RPAR | lhs T_LBRAK indices T_RBRAK | lhs T_HASH_LBRAK indices T_RBRAK | T_LPAR lhs T_RPAR ; ifstmt : T_IF T_LPAR expr T_RPAR body %prec T_THEN | T_IF T_LPAR expr T_RPAR body T_ELSE body ; whilestmt : T_WHILE T_LPAR expr T_RPAR body ; dostmt : T_DO body T_WHILE T_LPAR expr T_RPAR ; forstmt : T_FOR T_LPAR alst T_SEMI limit T_SEMI alst T_RPAR body ; forallstmt : T_FORALL T_LPAR expr T_RPAR body ; alst : /* NOTHING */ | assign_list ; assign_list : one_assign | assign_list T_COMMA one_assign ; one_assign : assign | lhs | T_VAR T_NAME T_EQUALS expr | T_VAR T_NAME T_COLON T_NAME T_EQUALS expr | T_STATIC T_NAME T_EQUALS expr | T_STATIC T_NAME T_COLON T_NAME T_EQUALS expr ; limit : /* NOTHING */ | expr ; switchstmt : T_SWITCH T_LPAR expr T_RPAR T_LBRACE cases T_RBRACE ; matchstmt : T_MATCH T_LPAR expr T_RPAR T_LBRACE cases T_RBRACE ; cases : /* NOTHING */ | cases onecase ; onecase : T_CASE exprlist T_COLON stmts | T_DEFAULT T_COLON stmts ; returnstmt : T_RETURN expr | T_RETURN ; assertstmt : T_ASSERT expr ; withstmt : T_WITH T_LPAR expr T_RPAR T_LBRACE obj_props T_RBRACE ; trystmt : T_TRY body T_CATCH T_LPAR names T_RPAR body ; throwstmt : T_THROW expr ; breakstmt : T_BREAK ; continuestmt : T_CONTINUE ; printstmt : T_STRING | T_STRING T_COMMA exprs | T_LSTRING | T_LSTRING T_COMMA exprs ; body : T_LBRACE stmts T_RBRACE | stmt ; exprs : /* NOTHING */ | exprlist ; exprlist : expr | exprlist T_COMMA expr ; expr : cond_expr | expr T_CONCAT cond_expr ; cond_expr : logor_expr | logor_expr T_QUEST expr T_COLON cond_expr ; logor_expr : logand_expr | logor_expr T_OROR logand_expr ; logand_expr : or_expr | logand_expr T_ANDAND or_expr ; or_expr : excl_or_expr | or_expr T_OR excl_or_expr ; excl_or_expr : and_expr | excl_or_expr T_XOR and_expr ; and_expr : equal_expr | and_expr T_AND equal_expr ; equal_expr : rel_expr | equal_expr T_EQEQ rel_expr | equal_expr T_NOTEQ rel_expr | equal_expr T_QUEST_EQ rel_expr | equal_expr T_MATCHES rel_expr | equal_expr T_HASH_EQ rel_expr ; rel_expr : shift_expr | rel_expr T_LT shift_expr | rel_expr T_GT shift_expr | rel_expr T_LE shift_expr | rel_expr T_GE shift_expr ; shift_expr : add_expr | shift_expr T_LSHIFT add_expr | shift_expr T_RSHIFT add_expr ; add_expr : mult_expr | add_expr T_PLUS mult_expr | add_expr T_MINUS mult_expr ; mult_expr : pow_expr | mult_expr T_STAR pow_expr | mult_expr T_SLASH pow_expr | mult_expr T_PCT pow_expr ; pow_expr : cvt_expr | cvt_expr T_STARSTAR pow_expr ; cvt_expr : unary_expr | cvt_expr T_EQGT unary_expr ; unary_expr : T_NOT unary_expr | T_BANG unary_expr | T_MINUS unary_expr | T_AT unary_expr | T_AT_AT unary_expr | T_QUEST_QUEST unary_expr | T_AND T_NAME | term ; indices : index | indices T_COMMA index ; index : expr | opt_expr T_COLON opt_expr | opt_expr T_COLON opt_expr T_COLON expr ; qual_name : T_NAME | T_NAME T_COLON_COLON T_NAME | T_COLON_COLON T_NAME ; term : qual_name | T_PUBLIC T_COLON_COLON T_NAME | T_LPAR expr T_RPAR | T_LPAR T_PROC T_RPAR /* ID of current proc */ | T_LBRACE exprs T_RBRACE /* Array decl */ | T_HASH_LBRACE exprs T_RBRACE /* Multimensional array decl */ | T_LLL exprs T_RRR /* Dict decl */ | T_LBRAK exprs T_RBRAK /* Packed array decl */ | T_LBRAK iterator T_RBRAK /* Iterator */ | T_STRING | T_LSTRING | T_INTCON | T_FLOATCON | T_CHARCON | T_LCHARCON | T_MATCH_ARG | T_MATCH_COUNT | T_LOOPBASE | T_NEW qual_name /* The create args are parsed */ | T_NEW T_LPAR expr T_RPAR /* by the CALL syntax below */ | T_PROC no_name_proc | T_PROC T_STRING no_name_proc | T_OPERATOR operator | T_BACKTICK operator | T_BACKTICK T_NAME /* Same as public::name */ | term T_LPAR exprs T_RPAR /* This is the CALL syntax */ | term T_LBRAK T_STAR T_RBRAK /* For "Array[*]" */ | term T_HASH_LPAR exprs T_RPAR | term T_DOT public | term T_LBRAK indices T_RBRAK | term T_HASH_LBRAK indices T_RBRAK | term T_LBRACE obj_props T_RBRACE /* For new and static obj */ | T_FOREACH T_LPAR expr T_RPAR T_LBRACE expr T_RBRACE ; iterator : opt_expr T_COLON opt_expr | opt_expr T_COLON opt_expr T_COLON opt_expr ; opt_expr : /* NOTHING */ | expr ; public : T_NAME | T_LPAR expr T_RPAR | T_OPERATOR operator | T_BACKTICK operator | T_BACKTICK T_NAME ;
The following lex / bison program properly tokenizes correct OADL programs:
/* * Copyright (c) 1997 Ross Cunniff * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ %{ #include "y.tab.h" #define YY_NO_UNISTD_H int line_num = 1; %} %x str %x comment /* This is a major hack. Rather than try to hand-enumerate all the possible * UTF-8 encodings of letter and digit characters, just assume that all * multibyte encodings are, effectively, letter characters. This * will accept valid programs but will not properly error on invalid * ones. */ U [\x80-\xbf] U2 [\xc2-\xdf] U3 [\xe0-\xef] U4 [\xf0-\xf7] UANY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} ALPHA [a-zA-Z$_]|{UANY} ALNUM [0-9a-zA-Z$_]|{UANY} DIGIT [0-9_] HEXDIGIT [0-9a-fA-F_] ESCAPE [0abfnrtv] ISIZE [ubslUBSL] FSIZE [hdHD] %% L\" BEGIN(str); \" BEGIN(str); <str>\" BEGIN(INITIAL); return T_STRING; <str>\\[0-7]{1,3} <str>\\0[xX]HEXDIGIT+ <str>\\(.|\n) <str>[^\\\n\"]+ L\'.\' return T_LCHARCON; \'.\' return T_CHARCON; \'\\.\' return T_CHARCON; {DIGIT}+{ISIZE}* return T_INTCON; "0"[xX]{HEXDIGIT}+{ISIZE}* return T_INTCON; {DIGIT}+"."{DIGIT}*{FSIZE}* return T_FLOATCON; {DIGIT}*"."{DIGIT}+{FSIZE}* return T_FLOATCON; {DIGIT}+"."{DIGIT}*[eE]{DIGIT}+{FSIZE}* return T_FLOATCON; {DIGIT}*"."{DIGIT}+[eE]{DIGIT}+{FSIZE}* return T_FLOATCON; {DIGIT}+"."{DIGIT}*[eE][+-]{DIGIT}+{FSIZE}* return T_FLOATCON; {DIGIT}*"."{DIGIT}+[eE][+-]{DIGIT}+{FSIZE}* return T_FLOATCON; {DIGIT}+[eE]{DIGIT}+{FSIZE}* return T_FLOATCON; {DIGIT}+[eE][+-]{DIGIT}+{FSIZE}* return T_FLOATCON; "?"{DIGIT}+ return T_MATCH_ARG; case return T_CASE; continue return T_CONTINUE; default return T_DEFAULT; do return T_DO; else return T_ELSE; extern return T_EXTERN; for return T_FOR; forall return T_FORALL; foreach return T_FOREACH; if return T_IF; return return T_RETURN; switch return T_SWITCH; while return T_WHILE; break return T_BREAK; class return T_CLASS; var return T_VAR; const return T_CONST; public return T_PUBLIC; proc return T_PROC; "#include" return T_INCLUDE; new return T_NEW; operator return T_OPERATOR; protected return T_PROTECTED; try return T_TRY; catch return T_CATCH; throw return T_THROW; assert return T_ASSERT; "#define" return T_DEFINE; match return T_MATCH; using return T_USING; namespace return T_NAMESPACE; with return T_WITH; static return T_STATIC; {ALPHA}{ALNUM}* return T_NAME; ";" return T_SEMI; "," return T_COMMA; "=" return T_EQUALS; "{" return T_LBRACE; "}" return T_RBRACE; "(" return T_LPAR; ")" return T_RPAR; "|" return T_OR; "^" return T_XOR; "&" return T_AND; "<" return T_LT; ">" return T_GT; "+" return T_PLUS; "-" return T_MINUS; "*" return T_STAR; "/" return T_SLASH; "%" return T_PCT; "~" return T_NOT; "!" return T_BANG; "." return T_DOT; "[" return T_LBRAK; "]" return T_RBRAK; ":" return T_COLON; "@" return T_AT; "?" return T_QUEST; "`" return T_BACKTICK; "**" return T_STARSTAR; "##" return T_CONCAT; "==" return T_EQEQ; "!=" return T_NOTEQ; "<=" return T_LE; ">=" return T_GE; "+=" return T_PLUSEQ; "-=" return T_MINUSEQ; "*=" return T_STAREQ; "/=" return T_SLASHEQ; "%=" return T_PCTEQ; "&=" return T_ANDEQ; "|=" return T_OREQ; "^=" return T_XOREQ; "<<" return T_LSHIFT; ">>" return T_RSHIFT; "&&" return T_ANDAND; "||" return T_OROR; "++" return T_PLUSPLUS; "--" return T_MINUSMINUS; "=>" return T_EQGT; "?=" return T_QUEST_EQ; "??" return T_QUEST_QUEST; "~=" return T_MATCHES; "?#" return T_MATCH_COUNT; "::" return T_COLON_COLON; "@@" return T_AT_AT; "#=" return T_HASH_EQ; "#[" return T_HASH_LBRAK; "#(" return T_HASH_LPAR; "#{" return T_HASH_LBRACE; "?*" return T_LOOPBASE; "!-" return T_BANG_MINUS; "->" return T_DOT; ":=" return T_COLON_EQUALS; "\\|" return T_OR_R; "\\^" return T_XOR_R; "\\&" return T_AND_R; "\\<" return T_LT_R; "\\>" return T_GT_R; "\\+" return T_PLUS_R; "\\-" return T_MINUS_R; "\\*" return T_STAR_R; "\\/" return T_SLASH_R; "\\%" return T_PCT_R; "\\**" return T_POW_R; "\\==" return T_EQEQ_R; "\\!=" return T_NOTEQ_R; "\\<=" return T_LE_R; "\\>=" return T_GE_R; "\\<<" return T_LSHIFT_R; "\\>>" return T_RSHIFT_R; "\\=>" return T_EQGT_R; "\\~=" return T_MATCHES_R; "<<=" return T_LSHIFTEQ; ">>=" return T_RSHIFTEQ; "<<<" return T_LLL; ">>>" return T_RRR; "..." return T_DOTDOTDOT; <<EOF>> return T_EOF; "//".*\n line_num++; "/*" BEGIN(comment); <comment>[^*\n]* <comment>"*"+[^*/\n]* <comment>\n line_num++; <comment>"*"+"/" BEGIN(INITIAL); "/*".*"*/" [ \t\r]+ \n line_num++; %% extern int yydebug; extern int yyparse(void); int main(int argc, char **argv) { if( (argc > 1) && (strcmp(argv[1], "-d") == 0) ) { yydebug = 1; } if( yyparse() == 0 ) { printf("success!\n"); } } void yyerror(char *s) { printf("failure at line %d\n", line_num); exit(1); } int yywrap(void) { return 1; }