1grammar t033backtracking; 2options { 3 language=Python3; 4 backtrack=true; 5 memoize=true; 6 k=2; 7} 8 9scope Symbols { 10 types; 11} 12 13@members { 14 def isTypeName(self, name): 15 for scope in reversed(self.Symbols_stack): 16 if name in scope.types: 17 return True 18 19 return False 20 21} 22 23translation_unit 24scope Symbols; // entire file is a scope 25@init { 26 $Symbols::types = set() 27} 28 : external_declaration+ 29 ; 30 31/** Either a function definition or any other kind of C decl/def. 32 * The LL(*) analysis algorithm fails to deal with this due to 33 * recursion in the declarator rules. I'm putting in a 34 * manual predicate here so that we don't backtrack over 35 * the entire function. Further, you get a better error 36 * as errors within the function itself don't make it fail 37 * to predict that it's a function. Weird errors previously. 38 * Remember: the goal is to avoid backtrack like the plague 39 * because it makes debugging, actions, and errors harder. 40 * 41 * Note that k=1 results in a much smaller predictor for the 42 * fixed lookahead; k=2 made a few extra thousand lines. ;) 43 * I'll have to optimize that in the future. 44 */ 45external_declaration 46options {k=1;} 47 : ( declaration_specifiers? declarator declaration* '{' )=> function_definition 48 | declaration 49 ; 50 51function_definition 52scope Symbols; // put parameters and locals into same scope for now 53@init { 54 $Symbols::types = set() 55} 56 : declaration_specifiers? declarator 57// ( declaration+ compound_statement // K&R style 58// | compound_statement // ANSI style 59// ) 60 ; 61 62declaration 63scope { 64 isTypedef; 65} 66@init { 67 $declaration::isTypedef = False 68} 69 : 'typedef' declaration_specifiers? {$declaration::isTypedef = True} 70 init_declarator_list ';' // special case, looking for typedef 71 | declaration_specifiers init_declarator_list? ';' 72 ; 73 74declaration_specifiers 75 : ( storage_class_specifier 76 | type_specifier 77 | type_qualifier 78 )+ 79 ; 80 81init_declarator_list 82 : init_declarator (',' init_declarator)* 83 ; 84 85init_declarator 86 : declarator //('=' initializer)? 87 ; 88 89storage_class_specifier 90 : 'extern' 91 | 'static' 92 | 'auto' 93 | 'register' 94 ; 95 96type_specifier 97 : 'void' 98 | 'char' 99 | 'short' 100 | 'int' 101 | 'long' 102 | 'float' 103 | 'double' 104 | 'signed' 105 | 'unsigned' 106// | struct_or_union_specifier 107// | enum_specifier 108 | type_id 109 ; 110 111type_id 112 : {self.isTypeName(self.input.LT(1).getText())}? IDENTIFIER 113// {System.out.println($IDENTIFIER.text+" is a type");} 114 ; 115 116// struct_or_union_specifier 117// options {k=3;} 118// scope Symbols; // structs are scopes 119// @init { 120// $Symbols::types = set() 121// } 122// : struct_or_union IDENTIFIER? '{' struct_declaration_list '}' 123// | struct_or_union IDENTIFIER 124// ; 125 126// struct_or_union 127// : 'struct' 128// | 'union' 129// ; 130 131// struct_declaration_list 132// : struct_declaration+ 133// ; 134 135// struct_declaration 136// : specifier_qualifier_list struct_declarator_list ';' 137// ; 138 139// specifier_qualifier_list 140// : ( type_qualifier | type_specifier )+ 141// ; 142 143// struct_declarator_list 144// : struct_declarator (',' struct_declarator)* 145// ; 146 147// struct_declarator 148// : declarator (':' constant_expression)? 149// | ':' constant_expression 150// ; 151 152// enum_specifier 153// options {k=3;} 154// : 'enum' '{' enumerator_list '}' 155// | 'enum' IDENTIFIER '{' enumerator_list '}' 156// | 'enum' IDENTIFIER 157// ; 158 159// enumerator_list 160// : enumerator (',' enumerator)* 161// ; 162 163// enumerator 164// : IDENTIFIER ('=' constant_expression)? 165// ; 166 167type_qualifier 168 : 'const' 169 | 'volatile' 170 ; 171 172declarator 173 : pointer? direct_declarator 174 | pointer 175 ; 176 177direct_declarator 178 : ( IDENTIFIER 179 { 180 if $declaration and $declaration::isTypedef: 181 $Symbols::types.add($IDENTIFIER.text) 182 print("define type "+$IDENTIFIER.text) 183 } 184 | '(' declarator ')' 185 ) 186 declarator_suffix* 187 ; 188 189declarator_suffix 190 : /*'[' constant_expression ']' 191 |*/ '[' ']' 192// | '(' parameter_type_list ')' 193// | '(' identifier_list ')' 194 | '(' ')' 195 ; 196 197pointer 198 : '*' type_qualifier+ pointer? 199 | '*' pointer 200 | '*' 201 ; 202 203// parameter_type_list 204// : parameter_list (',' '...')? 205// ; 206 207// parameter_list 208// : parameter_declaration (',' parameter_declaration)* 209// ; 210 211// parameter_declaration 212// : declaration_specifiers (declarator|abstract_declarator)* 213// ; 214 215// identifier_list 216// : IDENTIFIER (',' IDENTIFIER)* 217// ; 218 219// type_name 220// : specifier_qualifier_list abstract_declarator? 221// ; 222 223// abstract_declarator 224// : pointer direct_abstract_declarator? 225// | direct_abstract_declarator 226// ; 227 228// direct_abstract_declarator 229// : ( '(' abstract_declarator ')' | abstract_declarator_suffix ) abstract_declarator_suffix* 230// ; 231 232// abstract_declarator_suffix 233// : '[' ']' 234// | '[' constant_expression ']' 235// | '(' ')' 236// | '(' parameter_type_list ')' 237// ; 238 239// initializer 240// : assignment_expression 241// | '{' initializer_list ','? '}' 242// ; 243 244// initializer_list 245// : initializer (',' initializer)* 246// ; 247 248// // E x p r e s s i o n s 249 250// argument_expression_list 251// : assignment_expression (',' assignment_expression)* 252// ; 253 254// additive_expression 255// : (multiplicative_expression) ('+' multiplicative_expression | '-' multiplicative_expression)* 256// ; 257 258// multiplicative_expression 259// : (cast_expression) ('*' cast_expression | '/' cast_expression | '%' cast_expression)* 260// ; 261 262// cast_expression 263// : '(' type_name ')' cast_expression 264// | unary_expression 265// ; 266 267// unary_expression 268// : postfix_expression 269// | '++' unary_expression 270// | '--' unary_expression 271// | unary_operator cast_expression 272// | 'sizeof' unary_expression 273// | 'sizeof' '(' type_name ')' 274// ; 275 276// postfix_expression 277// : primary_expression 278// ( '[' expression ']' 279// | '(' ')' 280// | '(' argument_expression_list ')' 281// | '.' IDENTIFIER 282// | '*' IDENTIFIER 283// | '->' IDENTIFIER 284// | '++' 285// | '--' 286// )* 287// ; 288 289// unary_operator 290// : '&' 291// | '*' 292// | '+' 293// | '-' 294// | '~' 295// | '!' 296// ; 297 298// primary_expression 299// : IDENTIFIER 300// | constant 301// | '(' expression ')' 302// ; 303 304// constant 305// : HEX_LITERAL 306// | OCTAL_LITERAL 307// | DECIMAL_LITERAL 308// | CHARACTER_LITERAL 309// | STRING_LITERAL 310// | FLOATING_POINT_LITERAL 311// ; 312 313// ///// 314 315// expression 316// : assignment_expression (',' assignment_expression)* 317// ; 318 319// constant_expression 320// : conditional_expression 321// ; 322 323// assignment_expression 324// : lvalue assignment_operator assignment_expression 325// | conditional_expression 326// ; 327 328// lvalue 329// : unary_expression 330// ; 331 332// assignment_operator 333// : '=' 334// | '*=' 335// | '/=' 336// | '%=' 337// | '+=' 338// | '-=' 339// | '<<=' 340// | '>>=' 341// | '&=' 342// | '^=' 343// | '|=' 344// ; 345 346// conditional_expression 347// : logical_or_expression ('?' expression ':' conditional_expression)? 348// ; 349 350// logical_or_expression 351// : logical_and_expression ('||' logical_and_expression)* 352// ; 353 354// logical_and_expression 355// : inclusive_or_expression ('&&' inclusive_or_expression)* 356// ; 357 358// inclusive_or_expression 359// : exclusive_or_expression ('|' exclusive_or_expression)* 360// ; 361 362// exclusive_or_expression 363// : and_expression ('^' and_expression)* 364// ; 365 366// and_expression 367// : equality_expression ('&' equality_expression)* 368// ; 369// equality_expression 370// : relational_expression (('=='|'!=') relational_expression)* 371// ; 372 373// relational_expression 374// : shift_expression (('<'|'>'|'<='|'>=') shift_expression)* 375// ; 376 377// shift_expression 378// : additive_expression (('<<'|'>>') additive_expression)* 379// ; 380 381// // S t a t e m e n t s 382 383// statement 384// : labeled_statement 385// | compound_statement 386// | expression_statement 387// | selection_statement 388// | iteration_statement 389// | jump_statement 390// ; 391 392// labeled_statement 393// : IDENTIFIER ':' statement 394// | 'case' constant_expression ':' statement 395// | 'default' ':' statement 396// ; 397 398// compound_statement 399// scope Symbols; // blocks have a scope of symbols 400// @init { 401// $Symbols::types = {} 402// } 403// : '{' declaration* statement_list? '}' 404// ; 405 406// statement_list 407// : statement+ 408// ; 409 410// expression_statement 411// : ';' 412// | expression ';' 413// ; 414 415// selection_statement 416// : 'if' '(' expression ')' statement (options {k=1; backtrack=false;}:'else' statement)? 417// | 'switch' '(' expression ')' statement 418// ; 419 420// iteration_statement 421// : 'while' '(' expression ')' statement 422// | 'do' statement 'while' '(' expression ')' ';' 423// | 'for' '(' expression_statement expression_statement expression? ')' statement 424// ; 425 426// jump_statement 427// : 'goto' IDENTIFIER ';' 428// | 'continue' ';' 429// | 'break' ';' 430// | 'return' ';' 431// | 'return' expression ';' 432// ; 433 434IDENTIFIER 435 : LETTER (LETTER|'0'..'9')* 436 ; 437 438fragment 439LETTER 440 : '$' 441 | 'A'..'Z' 442 | 'a'..'z' 443 | '_' 444 ; 445 446CHARACTER_LITERAL 447 : '\'' ( EscapeSequence | ~('\''|'\\') ) '\'' 448 ; 449 450STRING_LITERAL 451 : '"' ( EscapeSequence | ~('\\'|'"') )* '"' 452 ; 453 454HEX_LITERAL : '0' ('x'|'X') HexDigit+ IntegerTypeSuffix? ; 455 456DECIMAL_LITERAL : ('0' | '1'..'9' '0'..'9'*) IntegerTypeSuffix? ; 457 458OCTAL_LITERAL : '0' ('0'..'7')+ IntegerTypeSuffix? ; 459 460fragment 461HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ; 462 463fragment 464IntegerTypeSuffix 465 : ('u'|'U')? ('l'|'L') 466 | ('u'|'U') ('l'|'L')? 467 ; 468 469FLOATING_POINT_LITERAL 470 : ('0'..'9')+ '.' ('0'..'9')* Exponent? FloatTypeSuffix? 471 | '.' ('0'..'9')+ Exponent? FloatTypeSuffix? 472 | ('0'..'9')+ Exponent FloatTypeSuffix? 473 | ('0'..'9')+ Exponent? FloatTypeSuffix 474 ; 475 476fragment 477Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; 478 479fragment 480FloatTypeSuffix : ('f'|'F'|'d'|'D') ; 481 482fragment 483EscapeSequence 484 : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 485 | OctalEscape 486 ; 487 488fragment 489OctalEscape 490 : '\\' ('0'..'3') ('0'..'7') ('0'..'7') 491 | '\\' ('0'..'7') ('0'..'7') 492 | '\\' ('0'..'7') 493 ; 494 495fragment 496UnicodeEscape 497 : '\\' 'u' HexDigit HexDigit HexDigit HexDigit 498 ; 499 500WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} 501 ; 502 503COMMENT 504 : '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;} 505 ; 506 507LINE_COMMENT 508 : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 509 ; 510 511// ignore #line info for now 512LINE_COMMAND 513 : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 514 ; 515 516