package polyglot.parse; import polyglot.ast.*; import polyglot.lex.*; import polyglot.types.*; import polyglot.util.*; import java_cup.runtime.Symbol; import java.util.*; public abstract class BaseParser extends java_cup.runtime.lr_parser { public final Lexer lexer; public final ErrorQueue eq; public final TypeSystem ts; public final NodeFactory nf; protected Position prev_pos; protected Position position; public BaseParser (Lexer l, TypeSystem t, NodeFactory n, ErrorQueue q) { lexer = l; eq = q; ts = t; nf = n; prev_pos = Position.COMPILER_GENERATED; position = Position.COMPILER_GENERATED; } /** * The standard scanning routine for use in the CUP "scan with" * declaration. Should read: * scan with {: return nextSymbol(); :} */ public Symbol nextSymbol() throws java.io.IOException { Token t = lexer.nextToken(); // use two positions, since the parser does one token lookahead position = prev_pos; prev_pos = t.getPosition(); return t.symbol(); } public Position position() { return position; } /** * Override the default CUP routine. */ public void report_fatal_error (String message, Object info) throws Exception { report_error (message, info); die (); } /** * Report a fatal error then abort parsing. */ public void die (String msg, Position pos) throws Exception { report_fatal_error (msg, pos); } /** * Report a fatal error then abort parsing. */ public void die (Position pos) throws Exception { report_fatal_error ("Syntax error.", pos); } /** * Report a fatal error then abort parsing. */ public void die () throws Exception { done_parsing(); throw new Exception (); } protected Position posForObject(Object o) { if (o instanceof Node) { return pos ((Node) o); } else if (o instanceof Token) { return pos ((Token) o); } else if (o instanceof Type) { return pos ((Type) o); } else if (o instanceof List) { return pos ((List) o); } else if (o instanceof VarDeclarator) { return pos ((VarDeclarator) o); } else { return null; } } public Position pos(Object first, Object last){ return pos(first, last, first); } public Position pos(Object first, Object last, Object noEndDefault){ //System.out.println("first: "+first+" class: "+first.getClass()+" last: "+last+" class: "+last.getClass()); Position fpos = posForObject(first); Position epos = posForObject(last); if (fpos != null && epos != null) { if (epos.endColumn() != Position.END_UNUSED) { return new Position(fpos, epos); } // the end line and column are not being used in this extension. // so return the default for that case. return posForObject(noEndDefault); } return null; } /** * Return the position of the Token. */ public Position pos (Token t) { if (t == null) return null; return t.getPosition (); } /** * Return the source position of the Type. */ public Position pos (Type n) { if (n == null) return null; return n.position (); } /** * Return the source position of the first element in the list to the * last element in the list. */ public Position pos (List l) { if (l == null || l.isEmpty ()) { return null; } return pos(l.get(0), l.get(l.size()-1)); } /** * Return the source position of the declaration. */ public Position pos (VarDeclarator n) { if (n == null) return null; return n.pos; } /** * Return the source position of the Node. */ public Position pos (Node n) { if (n == null) { return null; } return n.position (); } /** * Return a TypeNode representing a <code>dims</code>-dimensional * array of <code>n</code>. */ public TypeNode array (TypeNode n, int dims) throws Exception { if (dims > 0) { if (n instanceof CanonicalTypeNode) { Type t = ((CanonicalTypeNode) n).type (); return nf.CanonicalTypeNode (pos (n), ts.arrayOf (t, dims)); } return nf.ArrayTypeNode (pos (n), array (n, dims - 1)); } else { return n; } } /** * Helper for exprToType. */ protected QualifierNode prefixToQualifier (Prefix p) throws Exception { if (p instanceof TypeNode) { return typeToQualifier ((TypeNode) p); } if (p instanceof Expr) { return exprToQualifier ((Expr) p); } if (p instanceof AmbReceiver) { AmbReceiver a = (AmbReceiver) p; if (a.prefix () != null) { return nf.AmbQualifierNode (pos (p), prefixToQualifier (a.prefix ()), a.name ()); } else { return nf.AmbQualifierNode (pos (p), a.name ()); } } if (p instanceof AmbPrefix) { AmbPrefix a = (AmbPrefix) p; if (a.prefix () != null) { return nf.AmbQualifierNode (pos (p), prefixToQualifier (a.prefix ()), a.name ()); } else { return nf.AmbQualifierNode (pos (p), a.name ()); } } die (pos (p)); return null; } /** * Helper for exprToType. */ protected QualifierNode typeToQualifier (TypeNode t) throws Exception { if (t instanceof AmbTypeNode) { AmbTypeNode a = (AmbTypeNode) t; if (a.qualifier () != null) { return nf.AmbQualifierNode (pos (t), a.qual (), a.name ()); } else { return nf.AmbQualifierNode (pos (t), a.name ()); } } die (pos (t)); return null; } /** * Helper for exprToType. */ protected QualifierNode exprToQualifier (Expr e) throws Exception { if (e instanceof AmbExpr) { AmbExpr a = (AmbExpr) e; return nf.AmbQualifierNode (pos (e), a.name ()); } if (e instanceof Field) { Field f = (Field) e; Receiver r = f.target (); return nf.AmbQualifierNode (pos (e), prefixToQualifier (r), f.name ()); } die (pos (e)); return null; } /** * Convert <code>e</code> into a type, yielding a <code>TypeNode</code>. * This is used by the cast_expression production. */ public TypeNode exprToType (Expr e) throws Exception { if (e instanceof AmbExpr) { AmbExpr a = (AmbExpr) e; return nf.AmbTypeNode (pos (e), a.name ()); } if (e instanceof Field) { Field f = (Field) e; Receiver r = f.target (); return nf.AmbTypeNode (pos (e), prefixToQualifier (r), f.name ()); } die (pos (e)); return null; } }