/* An EBNF grammar for EBNF */ [1] ebnf ::= (declaration | rule)* [2] declaration ::= '@terminals' | pass [3] rule ::= LHS expression # Use a terminal to match the identifier, rule name and assignment due to # confusion between the identifier RANGE [4] expression ::= alt [5] alt ::= seq ('|' seq)* [6] seq ::= diff+ [7] diff ::= postfix ('-' postfix)? [8] postfix ::= primary POSTFIX? [9] primary ::= HEX | SYMBOL | RANGE | O_RANGE | STRING1 | STRING2 | '(' expression ')' [10] pass ::= '@pass' expression @terminals [11] LHS ::= ('[' SYMBOL+ ']')? SYMBOL "::=" [12] SYMBOL ::= ([a-z] | [A-Z] | [0-9] | "_" | ".")+ [13] HEX ::= '#x' ([0-9]|[a-f]|[A-F])+ # Range is any combination of R_CHAR '-' R_CHAR or R_CHAR+ [14] RANGE ::= '[' ((R_BEGIN (HEX | R_CHAR)) | (HEX | R_CHAR))+ ']' # Range is any combination of R_CHAR '-' R_CHAR or R_CHAR+ preceded by ^ [15] O_RANGE ::= '[^' ((R_BEGIN (HEX | R_CHAR)) | (HEX | R_CHAR))+ ']' # Strings are unescaped Unicode, excepting control characters and hash (#) [16] STRING1 ::= '"' (CHAR - '"')* '"' [17] STRING2 ::= "'" (CHAR - "'")* "'" [18] CHAR ::= HEX | [#x20#x21#x22] | [#x24-#x00FFFFFF] [19] R_CHAR ::= CHAR - ']' [20] R_BEGIN ::= (HEX | R_CHAR) "-" # Should be able to do this inline, but not until terminal regular expressions are created automatically [21] POSTFIX ::= [?*+] [22] PASS ::= ( [#x00-#x20] | ( '#' | '//' ) [^#x0A#x0D]* | '/*' (( '*' [^/] )? | [^*] )* '*/' | '(*' (( '*' [^)] )? | [^*] )* '*)' )+ # Should be able to do this inline, but not until terminal regular expressions are created automatically @pass PASS