// ANSI C Yacc grammar, 1985 Jeff Lee, 1995 Jutta Degener // https://www.lysator.liu.se/c/ANSI-C-grammar-y.html use panfix::{pattern, Grammar, GrammarError, Parser, Visitor}; enum PrimaryExpr { Identifier(String), Integer(i64), Float(f64), String(String), } enum Expr { Unop(Unop, Box), Binop(Binop, Box, Box), FunctionCall(Box, Args), SizeOfType(TypeName), Cast(TypeName, Box), } enum Unop { PreInc, PostInc, PreDec, PostDec, AddrOf, Deref, Plus, Minus, LogicalNot, BitwiseNot, Sizeof } enum Binop { ArraySubscript, MemberAccess, MemberAccessPtr, Times, Divide, Modulo, Plus, Minus, } struct Args(Vec); fn make_c_parser() -> Result { // NOTE: Incomplete. Need to look up exact rules for C whitespace, identifiers, and numbers. let mut grammar = Grammar::new("[ \\t\\n\\r]+"); grammar.sort("Expr"); grammar.regex("identifier", "[a-zA-Z][a-zA-Z0-9]*")?; grammar.regex("integer", "[1-9][0-9]*")?; grammar.regex("float", "[0-9]+\\.[0-9]*")?; grammar.regex("string", r#""([^"\\]|\\.)*""#)?; grammar.op("parenthesized-expr", pattern!("(" Expr ")"))?; grammar.lgroup(); grammar.op("array-subscript", pattern!(_ "[" Expr "]"))?; // Must be either argument_expression_list or empty grammar.op("function-call", pattern!(_ "(" Expr ")"))?; // Must be '.' identifier grammar.op("member-access", pattern!(_ "." _))?; grammar.op("member-access-ptr", pattern!(_ "->" _))?; grammar.op("suffix-incr", pattern!(_ "++"))?; grammar.op("suffix-decr", pattern!(_ "--"))?; grammar.rgroup(); grammar.op("prefix-incr", pattern!("++" _))?; grammar.op("prefix-decr", pattern!("--" _))?; grammar.op("address-of", pattern!("&" _))?; grammar.op("dereference", pattern!("*" _))?; grammar.op("unary-plus", pattern!("+" _))?; grammar.op("unary-minus", pattern!("-" _))?; grammar.op("logical-not", pattern!("!" _))?; grammar.op("bitwise-not", pattern!("+" _))?; grammar.op("sizeof", pattern!("sizeof" _))?; grammar.op("sizeof-type", pattern!("sizeof(" Type ")"))?; grammar.rgroup(); grammar.op("cast", pattern!("(" Type ")" _))?; grammar.lgroup(); grammar.op("times", pattern!(_ "*" _))?; grammar.op("divide", pattern!(_ "/" _))?; grammar.op("modulo", pattern!(_ "%" _))?; grammar.lgroup(); grammar.op("plus", pattern!(_ "+" _))?; grammar.op("minus", pattern!(_ "-" _))?; // assignment_expression_list grammar.rgroup(); // Must join assignment_expressions grammar.op("args-list", pattern!(_ "," _))?; // waiting on: // type_name shift_expression : additive_expression | shift_expression LEFT_OP additive_expression | shift_expression RIGHT_OP additive_expression ; relational_expression : shift_expression | relational_expression '<' shift_expression | relational_expression '>' shift_expression | relational_expression LE_OP shift_expression | relational_expression GE_OP shift_expression ; equality_expression : relational_expression | equality_expression EQ_OP relational_expression | equality_expression NE_OP relational_expression ; and_expression : equality_expression | and_expression '&' equality_expression ; exclusive_or_expression : and_expression | exclusive_or_expression '^' and_expression ; inclusive_or_expression : exclusive_or_expression | inclusive_or_expression '|' exclusive_or_expression ; logical_and_expression : inclusive_or_expression | logical_and_expression AND_OP inclusive_or_expression ; logical_or_expression : logical_and_expression | logical_or_expression OR_OP logical_and_expression ; conditional_expression : logical_or_expression | logical_or_expression '?' expression ':' conditional_expression ; assignment_expression : conditional_expression | unary_expression assignment_operator assignment_expression ; assignment_operator : '=' | MUL_ASSIGN | DIV_ASSIGN | MOD_ASSIGN | ADD_ASSIGN | SUB_ASSIGN | LEFT_ASSIGN | RIGHT_ASSIGN | AND_ASSIGN | XOR_ASSIGN | OR_ASSIGN ; expression : assignment_expression | expression ',' assignment_expression ; constant_expression : conditional_expression ; declaration : declaration_specifiers ';' | declaration_specifiers init_declarator_list ';' ; declaration_specifiers : storage_class_specifier | storage_class_specifier declaration_specifiers | type_specifier | type_specifier declaration_specifiers | type_qualifier | type_qualifier declaration_specifiers ; init_declarator_list : init_declarator | init_declarator_list ',' init_declarator ; init_declarator : declarator | declarator '=' initializer ; storage_class_specifier : TYPEDEF | EXTERN | STATIC | AUTO | REGISTER ; type_specifier : VOID | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE | SIGNED | UNSIGNED | struct_or_union_specifier | enum_specifier | TYPE_NAME ; struct_or_union_specifier : struct_or_union IDENTIFIER '{' struct_declaration_list '}' | struct_or_union '{' struct_declaration_list '}' | struct_or_union IDENTIFIER ; struct_or_union : STRUCT | UNION ; struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration ; struct_declaration : specifier_qualifier_list struct_declarator_list ';' ; specifier_qualifier_list : type_specifier specifier_qualifier_list | type_specifier | type_qualifier specifier_qualifier_list | type_qualifier ; struct_declarator_list : struct_declarator | struct_declarator_list ',' struct_declarator ; struct_declarator : declarator | ':' constant_expression | declarator ':' constant_expression ; enum_specifier : ENUM '{' enumerator_list '}' | ENUM IDENTIFIER '{' enumerator_list '}' | ENUM IDENTIFIER ; enumerator_list : enumerator | enumerator_list ',' enumerator ; enumerator : IDENTIFIER | IDENTIFIER '=' constant_expression ; type_qualifier : CONST | VOLATILE ; declarator : pointer direct_declarator | direct_declarator ; direct_declarator : IDENTIFIER | '(' declarator ')' | direct_declarator '[' constant_expression ']' | direct_declarator '[' ']' | direct_declarator '(' parameter_type_list ')' | direct_declarator '(' identifier_list ')' | direct_declarator '(' ')' ; pointer : '*' | '*' type_qualifier_list | '*' pointer | '*' type_qualifier_list pointer ; type_qualifier_list : type_qualifier | type_qualifier_list type_qualifier ; parameter_type_list : parameter_list | parameter_list ',' ELLIPSIS ; parameter_list : parameter_declaration | parameter_list ',' parameter_declaration ; parameter_declaration : declaration_specifiers declarator | declaration_specifiers abstract_declarator | declaration_specifiers ; identifier_list : IDENTIFIER | identifier_list ',' IDENTIFIER ; type_name : specifier_qualifier_list | specifier_qualifier_list abstract_declarator ; abstract_declarator : pointer | direct_abstract_declarator | pointer direct_abstract_declarator ; direct_abstract_declarator : '(' abstract_declarator ')' | '[' ']' | '[' constant_expression ']' | direct_abstract_declarator '[' ']' | direct_abstract_declarator '[' constant_expression ']' | '(' ')' | '(' parameter_type_list ')' | direct_abstract_declarator '(' ')' | direct_abstract_declarator '(' parameter_type_list ')' ; initializer : assignment_expression | '{' initializer_list '}' | '{' initializer_list ',' '}' ; initializer_list : initializer | initializer_list ',' initializer ; statement : labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement ; labeled_statement : IDENTIFIER ':' statement | CASE constant_expression ':' statement | DEFAULT ':' statement ; compound_statement : '{' '}' | '{' statement_list '}' | '{' declaration_list '}' | '{' declaration_list statement_list '}' ; declaration_list : declaration | declaration_list declaration ; statement_list : statement | statement_list statement ; expression_statement : ';' | expression ';' ; selection_statement : IF '(' expression ')' statement | IF '(' expression ')' statement ELSE statement | SWITCH '(' expression ')' statement ; iteration_statement : WHILE '(' expression ')' statement | DO statement WHILE '(' expression ')' ';' | FOR '(' expression_statement expression_statement ')' statement | FOR '(' expression_statement expression_statement expression ')' statement ; jump_statement : GOTO IDENTIFIER ';' | CONTINUE ';' | BREAK ';' | RETURN ';' | RETURN expression ';' ; translation_unit : external_declaration | translation_unit external_declaration ; external_declaration : function_definition | declaration ; function_definition : declaration_specifiers declarator declaration_list compound_statement | declaration_specifiers declarator compound_statement | declarator declaration_list compound_statement | declarator compound_statement ; %% #include extern char yytext[]; extern int column; yyerror(s) char *s; { fflush(stdout); printf("\n%*s\n%*s\n", column, "^", column, s); } */