keywords.ebnf (1558B)
1 // C-ish "kitchen sink" lexer fixture for explicit keyword extraction. The 2 // %keywords block lists string-literal tokens shadowed by IDENT; they are kept 3 // out of the DFA and recovered by a minimal perfect hash at runtime. Exercises 4 // all three entry forms (NAME = "lit", bare "lit", bare NAME) alongside `+`, 5 // `%def` fragments, line comments, and numeric literals with `_` separators. 6 // Byte mode, so it also builds under NO_UNICODE; held byte-identical across the 7 // C and Python generators by the parity stamps and driven by test_keywords.c. 8 %token TYPEDEF = "typedef"; 9 10 %lex { 11 %def digit = [0-9]; 12 %def hexit = [0-9a-fA-F]; 13 %def alpha = [A-Za-z_]; 14 15 %skip WS = \s+; 16 %skip LINE_COMMENT = "//" [^\n]*; 17 18 HEX = "0x" hexit ("_"? hexit)*; 19 FLOAT = digit+ "." digit+ (("e" | "E") ("+" | "-")? digit+)?; 20 INT = digit ("_"? digit)*; 21 STRING = "\"" ("\\" [^\n] | [^"\\\n])* "\""; 22 IDENT = alpha (alpha | digit)*; 23 24 %keywords IDENT { 25 IF = "if"; 26 ELSE = "else"; 27 WHILE = "while"; 28 FOR = "for"; 29 RETURN = "return"; 30 BREAK = "break"; 31 CONTINUE = "continue"; 32 STRUCT = "struct"; 33 "sizeof"; // bare string: auto-named token SIZEOF 34 TYPEDEF; // bare name: lexeme from the %token declaration above 35 } 36 37 LPAREN = "("; 38 RPAREN = ")"; 39 SEMI = ";"; 40 ASSIGN = "="; 41 PLUS = "+"; 42 } 43 44 program = stmt*; 45 stmt = IF | ELSE | WHILE | FOR | RETURN | BREAK | CONTINUE | STRUCT | SIZEOF | TYPEDEF 46 | HEX | FLOAT | INT | STRING | IDENT | LPAREN | RPAREN | SEMI | ASSIGN | PLUS;