package se.chalmers.cs.pgf.raw; import se.chalmers.cs.pgf.PGFException; import static se.chalmers.cs.pgf.raw.Lexer.Token; import static se.chalmers.cs.pgf.raw.Lexer.TokenType.*; import java.util.*; public class PGFParser { private Lexer lexer; private Token lastToken = null; private PGFParser(Lexer lexer) { this.lexer = lexer; } private Grm pGrm() { return new Grm(pTerms()); } private Term[] pTerms() { List ts = new LinkedList(); Term t; while (!lexer.isDone() && (t = pTerm(1)) != null) { ts.add(t); } return ts.toArray(new Term[ts.size()]); } private void nextToken() { lastToken = lexer.nextToken(); } private Term pTerm(int prec) { nextToken(); switch (lastToken.type) { case OPEN_PAREN: return pTermTop(); // the closing parenthesis will be consumed by the // null-returning call to pTerm in pTerms case CLOSE_PAREN: return null; case IDENT: return new Fun(lastToken.str, prec == 0 ? pTerms() : new Term[0]); case STRING: return new Lit(new LStr(lastToken.str)); case INTEGER: return new Lit(new LInt(Integer.parseInt(lastToken.str))); case DOUBLE: return new Lit(new LFlt(Double.parseDouble(lastToken.str))); case META: return new Met(); default: // should never happen throw new ParseException("found unknown token type"); } } private Term pTermTop() { Term t = pTerm(0); if (t == null) throw new ParseException("expected Term"); return t; } public static Grm parseGrm(CharSequence input) { return new PGFParser(new Lexer(input)).pGrm(); } public static Term parseTerm(CharSequence input) { return new PGFParser(new Lexer(input)).pTermTop(); } public class ParseException extends PGFException { public ParseException(String msg) { super("At character " + lexer.getPos() + ", " + msg + ", found: " + lastToken); } } }