1{ 2#include <stdio.h> 3#include <string.h> 4 5char *reserved_words[] = { "auto", "break", "case", "char", "const", 6 "continue", "default", "do", "double", "else", "enum", "extern", "float", 7 "for", "goto", "if", "int", "long", "register", "return", "short", "signed", 8 "sizeof", "static", "struct", "typedef", "union", "unsigned", "void", 9 "volatile", "while", NULL}; 10 11static int is_one_of(char *s, char *e, char **list) { 12 while (*list) { 13 if (strlen(*list) == e-s && !strncmp(s, *list, e-s)) return 1; 14 list++; 15 } 16 return 0; 17} 18} 19 20program: statements ; 21 22statements: statement*; 23statements_expr: statements expression?; 24statement: function_definition 25 | declaration ';' 26 | expression ';' 27 | '{' statements_expr '}'; 28 29function_definition 30 : declaration_specifiers declarator '{' statements_expr '}' ; 31 32declaration : declaration_specifiers init_declarator_list? ; 33 34init_declarator_list : init_declarator (',' init_declarator)* ; 35init_declarator : declarator ('=' initializer)? ; 36 37declaration_specifiers 38 : (storage_class_specifier | type_specifier | type_qualifier)+ ; 39 40storage_class_specifier: 'auto' | 'register' | 'static' | 'extern' | 'typedef'; 41 42type_specifier: 'void' | 'char' | 'short' | 'int' | 'long' | 'float' 43 | 'double' | 'signed' | 'unsigned' | struct_or_union_specifier 44 | enum_specifier | typeID; 45 46type_qualifier: 'const' | 'volatile'; 47 48typeID: identifier [ 49/* 50 D_Sym *s = find_sym(${scope}, $n0.start, $n0.end); 51 if (!s) ${reject}; 52 if (!s->user.is_typename) ${reject}; 53*/ 54]; 55 56struct_or_union_specifier: ('struct' | 'union') 57 ( identifier | identifier? '{' struct_declaration+ '}') ; 58 59struct_declaration : specifier_qualifier_list struct_declarator_list ';' ; 60 61specifier_qualifier_list : (type_specifier | type_qualifier)+ ; 62 63struct_declarator_list : struct_declarator (',' struct_declarator)* ; 64 65struct_declarator : declarator | declarator? ':' constant; 66 67enum_specifier : 'enum' 68 ( identifier ('{' enumerator_list '}')? 69 | '{' enumerator_list '}') ; 70enumerator_list : enumerator (',' enumerator)* ; 71enumerator : identifier ('=' expression)?; 72 73declarator : '*' type_qualifier* declarator | direct_declarator ; 74 75direct_declarator : identifier declarator_suffix* 76 | '(' declarator ')' declarator_suffix* ; 77 78declarator_suffix : '[' expression? ']' | '(' parameter_list? ')'; 79 80parameter_list : parameter_declaration_list ( "," "..." )? ; 81 82parameter_declaration 83 : declaration_specifiers (declarator? | abstract_declarator) ; 84 85initializer : expr | '{' initializer (',' initializer)* '}' ; 86 87type_name : specifier_qualifier_list abstract_declarator ; 88 89abstract_declarator 90 : '*' type_qualifier* abstract_declarator 91 | '(' abstract_declarator ')' abstract_declarator_suffix+ 92 | ('[' expression? ']')+ 93 | ; 94 95abstract_declarator_suffix 96 : '[' expression? ']' 97 | '(' parameter_declaration_list? ')' ; 98 99parameter_declaration_list 100 : parameter_declaration ( ',' parameter_declaration )* ; 101 102expression 103 : expr 104 | expr ',' expr $left 6700 105 /* labels */ 106 | identifier ':' expression $right 6600 107 | 'case' expression ':' expression $right 6500 108 | 'default' ':' expression $right 6500 109 /* conditionals */ 110 | 'if' '(' statements_expr ')' expression $right 6000 111 | 'if' '(' statements_expr ')' statement 'else' expression $right 6100 112 | 'switch' '(' statements_expr ')' expression $right 6200 113 /* loops */ 114 | 'while' '(' statements_expr ')' expression $right 6300 115 | 'do' statement 'while' expression $right 6400 116 | 'for' '(' expression (';' expression (';' expression)?)? ')' 117 expression $right 6500 118 /* jump */ 119 | 'goto' expression? 120 | 'continue' expression? 121 | 'break' expression? 122 | 'return' expression? 123 | expression juxiposition expression 124 ; 125 126juxiposition: $binary_op_left 5000; 127 128expr 129 : identifier 130 | constant 131 | strings 132 | '(' statements_expr')' 133 | '[' statements_expr ']' 134 | '{' statements_expr '}' 135 | expr '?' expression ':' expr $right 8600 136 /* post operators */ 137 | expr '--' $left 9900 138 | expr '++' $left 9900 139 | expr '(' statements_expr ')' $left 9900 140 | expr '[' statements_expr ']' $left 9900 141 | expr '{' statements_expr '}' $left 9900 142 /* pre operators */ 143 | 'sizeof' expression $right 9900 144 | '-' expr $right 9800 145 | '+' expr $right 9800 146 | '~' expr $right 9800 147 | '!' expr $right 9800 148 | '*' expr $right 9800 149 | '&' expr $right 9800 150 | '--' expr $right 9800 151 | '++' expr $right 9800 152 | '(' type_name ')' expr $right 9800 153 /* binary operators */ 154 | expr '->' expr $left 9900 155 | expr '.' expr $left 9900 156 | expr '*' expr $left 9600 157 | expr '/' expr $left 9600 158 | expr '%' expr $left 9600 159 | expr '+' expr $left 9500 160 | expr '-' expr $left 9500 161 | expr '<<' expr $left 9400 162 | expr '>>' expr $left 9400 163 | expr '<' expr $left 9300 164 | expr '<=' expr $left 9300 165 | expr '>' expr $left 9300 166 | expr '>=' expr $left 9300 167 | expr '==' expr $left 9200 168 | expr '!=' expr $left 9200 169 | expr '&' expr $left 9100 170 | expr '^' expr $left 9000 171 | expr '|' expr $left 8900 172 | expr '&&' expr $left 8800 173 | expr '||' expr $left 8700 174 | expr '=' expr $left 8500 175 | expr '*=' expr $left 8500 176 | expr '/=' expr $left 8500 177 | expr '%=' expr $left 8500 178 | expr '+=' expr $left 8500 179 | expr '-=' expr $left 8500 180 | expr '<<=' expr $left 8500 181 | expr '>>=' expr $left 8500 182 | expr '&=' expr $left 8500 183 | expr '|=' expr $left 8500 184 | expr '^=' expr $left 8500 185 | expr application expr 186 ; 187 188application: $binary_op_left 7000; 189 190strings: string | strings string $left 10000; 191constant : decimalint | hexint | octalint | character | float1 | float2; 192character: "'[^']*'"; 193string: "\"[^\"]*\""; 194decimalint: "[1-9][0-9]*[uUlL]?" $term -1; 195hexint: "(0x|0X)[0-9a-fA-F]+[uUlL]?" $term -2; 196octalint: "0[0-7]*[uUlL]?" $term -3; 197float1: "([0-9]+.[0-9]*|[0-9]*.[0-9]+)([eE][\-\+]?[0-9]+)?[fFlL]?" $term -4; 198float2: "[0-9]+[eE][\-\+]?[0-9]+[fFlL]?" $term -5; 199identifier: "[a-zA-Z_][a-zA-Z0-9_]*" $term -6 [ 200 if (is_one_of($n0.start, $n0.end, reserved_words)) 201 ${reject}; 202]; 203