+ private Grammar parseGrammar(Grammar g) throws IOException {
+ int tok = getToken();
+ if (g != null)
+ switch(tok) {
+ case BITOR: return new Grammar.Alternative(g, parseGrammar(null));
+ case ADD: return parseGrammar(new Grammar.Repetition(g, 1, Integer.MAX_VALUE));
+ case MUL: return parseGrammar(new Grammar.Repetition(g, 0, Integer.MAX_VALUE));
+ case HOOK: return parseGrammar(new Grammar.Repetition(g, 0, 1));
+ }
+ Grammar g0 = null;
+ switch(tok) {
+ //case NUMBER: g0 = new Grammar.Literal(number); break;
+ case NAME: g0 = new Grammar.Reference(string); break;
+ case STRING:
+ g0 = new Grammar.Literal(string);
+ if (peekToken() == DOT) {
+ String old = string;
+ consume(DOT);
+ consume(DOT);
+ consume(STRING);
+ if (old.length() != 1 || string.length() != 1) throw pe("literal ranges must be single-char strings");
+ g0 = new Grammar.Range(old.charAt(0), string.charAt(0));
+ }
+ break;
+ case LP: g0 = parseGrammar(null); consume(RP); break;
+ default: pushBackToken(); return g;
+ }
+ if (g == null) return parseGrammar(g0);
+ return parseGrammar(new Grammar.Juxtaposition(g, g0));
+ }