package oops3; public class XbnfParser { %% # XBNF-style grammar for extended EBNF # ( x ) for precedence # x | y for mutually exclusive alternatives # [ x, y ] for inclusive alternatives (unordered subset) # [ x, y ] / delim ... with delimiters # { x, y } for all alternatives (unordered full set) # { x, y } / delim ... with delimiters # x ? for optional items # x + for one or more iterations # x * for zero or more iterations # x number for a number of iterations # x from..to for a range of iterations # x ..max for zero to max iterations # x min.. for min or more iterations # x .. for zero or more iterations # x range / delim ... any (non-singleton) range with delimiters # skip patterns Comment = '#.*'; WhiteSpace = '[ \r\t\n]+'; # token patterns (these are placeholders for a hand-crafted scanner) Prolog = '.*%%'; Id = '[a-zA-Z_][-a-zA-Z_0-9.$]*'; String = '\'([^\'\\\r\n]|\\.)*\''; Number = '[1-9][0-9]*'; Epilog = '%%.*'; # RFC-style rules parser: Prolog rule+ Epilog; rule: type? Id ( pattern | rhs ) ';'; type: '<' ( Id ( ':' Id +/ ',' )? '>' '?'? | '>' ); pattern: '=' String; rhs: ':' xor; xor: sequence +/ '|'; sequence: term+; literal: String; optional: '?'; some: '+' list?; many: '*' list?; list: '/' item; # changed rules term: item range?; item: Id | literal | '(' xor ')' | or | and; or: '[' xor 2../ ',' ']' list?; and: '{' xor 2../ ',' '}' list?; range: range1 | range2 | optional | some | many; range1: Number ( '..' Number? list? | list )?; range2: '..' ( Number? list? )?; %% }