diff --git a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java index 4ae33bdde59..0934469655b 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java +++ b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java @@ -15,14 +15,13 @@ */ package com.google.gwt.dev.js; -import org.jetbrains.kotlin.js.backend.ast.*; -import org.jetbrains.kotlin.js.backend.ast.JsBooleanLiteral; -import org.jetbrains.kotlin.js.backend.ast.metadata.HasMetadata; import com.google.gwt.dev.js.parserExceptions.JsParserException; -import com.google.gwt.dev.js.rhino.*; +import com.google.gwt.dev.js.rhino.Node; +import com.google.gwt.dev.js.rhino.TokenStream; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.js.backend.ast.*; import java.util.ArrayList; import java.util.List; @@ -40,8 +39,7 @@ public class JsAstMapper { } private static JsParserException createParserException(String msg, Node offender) { - CodePosition position = new CodePosition(offender.getLineno(), 0); - return new JsParserException("Parser encountered internal error: " + msg, position); + return new JsParserException("Parser encountered internal error: " + msg, offender.getPosition()); } private JsNode map(Node node) throws JsParserException { @@ -254,7 +252,7 @@ public class JsAstMapper { private JsExpression mapAssignmentVariant(Node asgNode) throws JsParserException { - switch (asgNode.getIntDatum()) { + switch (asgNode.getOperation()) { case TokenStream.NOP: return mapBinaryOperation(JsBinaryOperator.ASG, asgNode); @@ -293,7 +291,7 @@ public class JsAstMapper { default: throw createParserException("Unknown assignment operator variant: " - + asgNode.getIntDatum(), asgNode); + + asgNode.getOperation(), asgNode); } } @@ -434,7 +432,7 @@ public class JsAstMapper { } private JsExpression mapEqualityVariant(Node eqNode) throws JsParserException { - switch (eqNode.getIntDatum()) { + switch (eqNode.getOperation()) { case TokenStream.EQ: return mapBinaryOperation(JsBinaryOperator.EQ, eqNode); @@ -461,18 +459,13 @@ public class JsAstMapper { default: throw createParserException("Unknown equality operator variant: " - + eqNode.getIntDatum(), eqNode); + + eqNode.getOperation(), eqNode); } } private JsExpression mapExpression(Node exprNode) throws JsParserException { JsNode unknown = map(exprNode); - if (unknown instanceof HasMetadata) { - HasMetadata metadataContainer = (HasMetadata) unknown; - metadataContainer.setData("line", exprNode.getLineno()); - } - if (unknown instanceof JsExpression) { return (JsExpression) unknown; } @@ -611,16 +604,8 @@ public class JsAstMapper { JsExpression toQualifier = mapExpression(from1); JsNameRef toNameRef; - if (from2 != null) { - toNameRef = mapAsPropertyNameRef(from2); - } - else { - // Special properties don't have a second expression. - // - Object obj = getPropNode.getProp(Node.SPECIAL_PROP_PROP); - assert (obj instanceof String); - toNameRef = scopeContext.referenceFor((String) obj); - } + toNameRef = mapAsPropertyNameRef(from2); + toNameRef.setQualifier(toQualifier); return toNameRef; @@ -649,14 +634,14 @@ public class JsAstMapper { private JsExpression mapIncDecFixity(JsUnaryOperator op, Node node) throws JsParserException { - switch (node.getIntDatum()) { + switch (node.getOperation()) { case TokenStream.PRE: return mapPrefixOperation(op, node); case TokenStream.POST: return mapPostfixOperation(op, node); default: throw createParserException( - "Unknown prefix/postfix variant: " + node.getIntDatum(), node); + "Unknown prefix/postfix variant: " + node.getOperation(), node); } } @@ -761,7 +746,7 @@ public class JsAstMapper { } private static JsExpression mapPrimary(Node node) throws JsParserException { - switch (node.getIntDatum()) { + switch (node.getOperation()) { case TokenStream.THIS: return new JsThisRef(); @@ -778,7 +763,7 @@ public class JsAstMapper { return new JsNameRef("undefined"); default: - throw createParserException("Unknown primary: " + node.getIntDatum(), + throw createParserException("Unknown primary: " + node.getOperation(), node); } } @@ -799,7 +784,7 @@ public class JsAstMapper { private JsExpression mapRelationalVariant(Node relNode) throws JsParserException { - switch (relNode.getIntDatum()) { + switch (relNode.getOperation()) { case TokenStream.LT: return mapBinaryOperation(JsBinaryOperator.LT, relNode); @@ -820,7 +805,7 @@ public class JsAstMapper { default: throw createParserException("Unknown relational operator variant: " - + relNode.getIntDatum(), relNode); + + relNode.getOperation(), relNode); } } @@ -864,7 +849,7 @@ public class JsAstMapper { } private JsExpression mapShiftVariant(Node shiftNode) throws JsParserException { - switch (shiftNode.getIntDatum()) { + switch (shiftNode.getOperation()) { case TokenStream.LSH: return mapBinaryOperation(JsBinaryOperator.SHL, shiftNode); @@ -876,18 +861,13 @@ public class JsAstMapper { default: throw createParserException("Unknown equality operator variant: " - + shiftNode.getIntDatum(), shiftNode); + + shiftNode.getOperation(), shiftNode); } } private JsStatement mapStatement(Node nodeStmt) throws JsParserException { JsNode unknown = map(nodeStmt); - if (unknown instanceof HasMetadata) { - HasMetadata metadataContainer = (HasMetadata) unknown; - metadataContainer.setData("line", nodeStmt.getLineno()); - } - if (unknown != null) { if (unknown instanceof JsStatement) { return (JsStatement) unknown; @@ -1050,7 +1030,7 @@ public class JsAstMapper { } private JsExpression mapUnaryVariant(Node unOp) throws JsParserException { - switch (unOp.getIntDatum()) { + switch (unOp.getOperation()) { case TokenStream.SUB: return mapPrefixOperation(JsUnaryOperator.NEG, unOp); @@ -1077,7 +1057,7 @@ public class JsAstMapper { default: throw createParserException( - "Unknown unary operator variant: " + unOp.getIntDatum(), unOp); + "Unknown unary operator variant: " + unOp.getOperation(), unOp); } } diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java index fbd8d556972..1cd57442cdf 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java @@ -41,7 +41,6 @@ package com.google.gwt.dev.js.rhino; * @see Node */ public class IRFactory { - public IRFactory(TokenStream ts) { this.ts = ts; } @@ -49,77 +48,70 @@ public class IRFactory { /** * Script (for associating file/url names with toplevel scripts.) */ - public Object createScript(Object body, String sourceName, - int baseLineno, int endLineno, Object source) + public Node createScript(Node body) { Node result = new Node(TokenStream.SCRIPT); - Node children = ((Node) body).getFirstChild(); + Node children = body.getFirstChild(); if (children != null) result.addChildrenToBack(children); - - result.putProp(Node.SOURCENAME_PROP, sourceName); - result.putIntProp(Node.BASE_LINENO_PROP, baseLineno); - result.putIntProp(Node.END_LINENO_PROP, endLineno); - if (source != null) - result.putProp(Node.SOURCE_PROP, source); + return result; } /** * Leaf */ - public Object createLeaf(int nodeType) { - return new Node(nodeType); + public Node createLeaf(int nodeType, CodePosition location) { + return new Node(nodeType, location); } - public Object createLeaf(int nodeType, int nodeOp) { - return new Node(nodeType, nodeOp); + public Node createLeaf(int nodeType, int nodeOp, CodePosition location) { + return new Node(nodeType, nodeOp, location); } - public int getLeafType(Object leaf) { - Node n = (Node) leaf; - return n.getType(); + public int getLeafType(Node leaf) { + return leaf.getType(); } /** * Statement leaf nodes. */ - public Object createSwitch(int lineno) { - return new Node(TokenStream.SWITCH, lineno); + public Node createSwitch(CodePosition location) { + return new Node(TokenStream.SWITCH, location); } - public Object createVariables(int lineno) { - return new Node(TokenStream.VAR, lineno); + public Node createVariables(CodePosition location) { + return new Node(TokenStream.VAR, location); } - public Object createExprStatement(Object expr, int lineno) { - return new Node(TokenStream.EXPRSTMT, (Node) expr, lineno); + public Node createExprStatement(Object expr, CodePosition location) { + return new Node(TokenStream.EXPRSTMT, (Node) expr, location); } /** * Name */ - public Object createName(String name) { - return Node.newString(TokenStream.NAME, name); + public Node createName(String name, CodePosition location) { + return Node.newString(TokenStream.NAME, name, location); } /** * String (for literals) */ - public Object createString(String string) { - return Node.newString(string); + public Node createString(String string, CodePosition location) { + return Node.newString(string, location); } /** * Number (for literals) */ - public Object createNumber(int number) { - return Node.newNumber(number); + public Node createNumber(int number, CodePosition location) { + return Node.newNumber(number, location); } - public Object createNumber(double number) { - return Node.newNumber(number); + public Node createNumber(double number, CodePosition location) { + return Node.newNumber(number, location); } /** @@ -130,52 +122,47 @@ public class IRFactory { * @param stmts the statements in the catch clause * @param lineno the starting line number of the catch clause */ - public Object createCatch(String varName, Object catchCond, Object stmts, - int lineno) - { + public Node createCatch(Node varName, Node catchCond, Node stmts, CodePosition location) { if (catchCond == null) { - catchCond = new Node(TokenStream.PRIMARY, TokenStream.TRUE); + catchCond = new Node(TokenStream.PRIMARY, TokenStream.TRUE, location); } - return new Node(TokenStream.CATCH, (Node)createName(varName), - (Node)catchCond, (Node)stmts, lineno); + return new Node(TokenStream.CATCH, varName, catchCond, stmts, location); } /** * Throw */ - public Object createThrow(Object expr, int lineno) { - return new Node(TokenStream.THROW, (Node)expr, lineno); + public Node createThrow(Node expr, CodePosition location) { + return new Node(TokenStream.THROW, expr, location); } /** * Return */ - public Object createReturn(Object expr, int lineno) { + public Node createReturn(Node expr, CodePosition location) { return expr == null - ? new Node(TokenStream.RETURN, lineno) - : new Node(TokenStream.RETURN, (Node)expr, lineno); + ? new Node(TokenStream.RETURN, location) + : new Node(TokenStream.RETURN, expr, location); } /** * Label */ - public Object createLabel(String label, int lineno) { - Node result = new Node(TokenStream.LABEL, lineno); - Node name = Node.newString(TokenStream.NAME, label); - result.addChildToBack(name); + public Node createLabel(Node label, CodePosition location) { + Node result = new Node(TokenStream.LABEL, location); + result.addChildToBack(label); return result; } /** * Break (possibly labeled) */ - public Object createBreak(String label, int lineno) { - Node result = new Node(TokenStream.BREAK, lineno); + public Node createBreak(Node label, CodePosition location) { + Node result = new Node(TokenStream.BREAK, location); if (label == null) { return result; } else { - Node name = Node.newString(TokenStream.NAME, label); - result.addChildToBack(name); + result.addChildToBack(label); return result; } } @@ -183,13 +170,12 @@ public class IRFactory { /** * Continue (possibly labeled) */ - public Object createContinue(String label, int lineno) { - Node result = new Node(TokenStream.CONTINUE, lineno); + public Node createContinue(Node label, CodePosition location) { + Node result = new Node(TokenStream.CONTINUE, location); if (label == null) { return result; } else { - Node name = Node.newString(TokenStream.NAME, label); - result.addChildToBack(name); + result.addChildToBack(label); return result; } } @@ -197,8 +183,8 @@ public class IRFactory { /** * debugger */ - public Object createDebugger(int lineno) { - Node result = new Node(TokenStream.DEBUGGER, lineno); + public Node createDebugger(CodePosition location) { + Node result = new Node(TokenStream.DEBUGGER, location); return result; } @@ -207,81 +193,54 @@ public class IRFactory { * Creates the empty statement block * Must make subsequent calls to add statements to the node */ - public Object createBlock(int lineno) { - return new Node(TokenStream.BLOCK, lineno); + public Node createBlock(CodePosition location) { + return new Node(TokenStream.BLOCK, location); } - public Object createFunction(String name, Object args, Object statements, - String sourceName, int baseLineno, - int endLineno, Object source, - boolean isExpr) - { - Node f = new Node(TokenStream.FUNCTION, - Node.newString(TokenStream.NAME, - name == null ? "" : name), - (Node)args, (Node)statements, baseLineno); - - f.putProp(Node.SOURCENAME_PROP, sourceName); - f.putIntProp(Node.BASE_LINENO_PROP, baseLineno); - f.putIntProp(Node.END_LINENO_PROP, endLineno); - if (source != null) - f.putProp(Node.SOURCE_PROP, source); - - return f; - } - - /** - * Add a child to the back of the given node. This function - * breaks the Factory abstraction, but it removes a requirement - * from implementors of Node. - */ - public void addChildToBack(Object parent, Object child) { - ((Node)parent).addChildToBack((Node)child); + public Node createFunction(Node name, Node args, Node statements, CodePosition location) { + if (name == null) { + name = createName("", location); + } + return new Node(TokenStream.FUNCTION, name, args, statements, location); } /** * While */ - public Object createWhile(Object cond, Object body, int lineno) { - return new Node(TokenStream.WHILE, (Node)cond, (Node)body, lineno); + public Node createWhile(Node cond, Node body, CodePosition location) { + return new Node(TokenStream.WHILE, cond, body, location); } /** * DoWhile */ - public Object createDoWhile(Object body, Object cond, int lineno) { - return new Node(TokenStream.DO, (Node)body, (Node)cond, lineno); + public Node createDoWhile(Node body, Node cond, CodePosition location) { + return new Node(TokenStream.DO, body, cond, location); } /** * For */ - public Object createFor(Object init, Object test, Object incr, - Object body, int lineno) - { - return new Node(TokenStream.FOR, (Node)init, (Node)test, (Node)incr, - (Node)body); + public Node createFor(Node init, Node test, Node incr, Node body, CodePosition location) { + return new Node(TokenStream.FOR, init, test, incr, body, location); } /** * For .. In * */ - public Object createForIn(Object lhs, Object obj, Object body, int lineno) { - return new Node(TokenStream.FOR, (Node)lhs, (Node)obj, (Node)body); + public Node createForIn(Node lhs, Node obj, Node body, CodePosition location) { + return new Node(TokenStream.FOR, lhs, obj, body, location); } /** * Try/Catch/Finally */ - public Object createTryCatchFinally(Object tryblock, Object catchblocks, - Object finallyblock, int lineno) - { + public Node createTryCatchFinally(Node tryblock, Node catchblocks, Node finallyblock, CodePosition location) { if (finallyblock == null) { - return new Node(TokenStream.TRY, (Node)tryblock, (Node)catchblocks); + return new Node(TokenStream.TRY, tryblock, catchblocks, location); } - return new Node(TokenStream.TRY, (Node)tryblock, - (Node)catchblocks, (Node)finallyblock); + return new Node(TokenStream.TRY, tryblock, catchblocks, finallyblock, location); } /** @@ -291,81 +250,70 @@ public class IRFactory { /** * With */ - public Object createWith(Object obj, Object body, int lineno) { - return new Node(TokenStream.WITH, (Node)obj, (Node)body, lineno); + public Node createWith(Node obj, Node body, CodePosition location) { + return new Node(TokenStream.WITH, obj, body, location); } /** * Array Literal */ - public Object createArrayLiteral(Object obj) { + public Node createArrayLiteral(Node obj) { return obj; } /** * Object Literals */ - public Object createObjectLiteral(Object obj) { + public Node createObjectLiteral(Node obj) { return obj; } /** * Regular expressions */ - public Object createRegExp(String string, String flags) { + public Node createRegExp(String string, String flags, CodePosition location) { return flags.length() == 0 ? new Node(TokenStream.REGEXP, - Node.newString(string)) + Node.newString(string, location), location) : new Node(TokenStream.REGEXP, - Node.newString(string), - Node.newString(flags)); + Node.newString(string, location), + Node.newString(flags, location), + location); } /** * If statement */ - public Object createIf(Object cond, Object ifTrue, Object ifFalse, - int lineno) - { + public Node createIf(Node cond, Node ifTrue, Node ifFalse, CodePosition location) { if (ifFalse == null) - return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, lineno); - return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, (Node)ifFalse, lineno); + return new Node(TokenStream.IF, cond, ifTrue, location); + return new Node(TokenStream.IF, cond, ifTrue, ifFalse, location); } - public Object createTernary(Object cond, Object ifTrue, Object ifFalse) { - return new Node(TokenStream.HOOK, - (Node)cond, (Node)ifTrue, (Node)ifFalse); + public Node createTernary(Node cond, Node ifTrue, Node ifFalse, CodePosition location) { + return new Node(TokenStream.HOOK, cond, ifTrue, ifFalse, location); } /** * Unary */ - public Object createUnary(int nodeType, Object child) { - Node childNode = (Node) child; - return new Node(nodeType, childNode); + public Node createUnary(int nodeType, Node child, CodePosition location) { + return new Node(nodeType, child, location); } - public Object createUnary(int nodeType, int nodeOp, Object child) { - return new Node(nodeType, (Node)child, nodeOp); + public Node createUnary(int nodeType, int nodeOp, Node child, CodePosition location) { + return new Node(nodeType, child, nodeOp, location); } /** * Binary */ - public Object createBinary(int nodeType, Object left, Object right) { - Node temp; + public Node createBinary(int nodeType, Node left, Node right, CodePosition location) { switch (nodeType) { case TokenStream.DOT: nodeType = TokenStream.GETPROP; - Node idNode = (Node) right; - idNode.setType(TokenStream.STRING); - String id = idNode.getString(); - if (id.equals("__proto__") || id.equals("__parent__")) { - Node result = new Node(nodeType, (Node) left); - result.putProp(Node.SPECIAL_PROP_PROP, id); - return result; - } + right.setType(TokenStream.STRING); break; case TokenStream.LB: @@ -373,22 +321,17 @@ public class IRFactory { nodeType = TokenStream.GETELEM; break; } - return new Node(nodeType, (Node)left, (Node)right); + return new Node(nodeType, left, right, location); } - public Object createBinary(int nodeType, int nodeOp, Object left, - Object right) - { + public Node createBinary(int nodeType, int nodeOp, Node left, Node right, CodePosition location) { if (nodeType == TokenStream.ASSIGN) { - return createAssignment(nodeOp, (Node) left, (Node) right, - null, false); + return createAssignment(nodeOp, left, right, location); } - return new Node(nodeType, (Node) left, (Node) right, nodeOp); + return new Node(nodeType, left, right, nodeOp, location); } - public Object createAssignment(int nodeOp, Node left, Node right, - Class convert, boolean postfix) - { + public Node createAssignment(int nodeOp, Node left, Node right, CodePosition location) { int nodeType = left.getType(); switch (nodeType) { case TokenStream.NAME: @@ -401,7 +344,7 @@ public class IRFactory { reportError("msg.bad.lhs.assign"); } - return new Node(TokenStream.ASSIGN, left, right, nodeOp); + return new Node(TokenStream.ASSIGN, left, right, nodeOp, location); } private void reportError(String msgResource) { diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java index 67b448ad447..fbf1a3b95f1 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java @@ -46,13 +46,13 @@ public class Node implements Cloneable { private static class NumberNode extends Node { - NumberNode(int number) { - super(TokenStream.NUMBER_INT); + NumberNode(int number, CodePosition location) { + super(TokenStream.NUMBER_INT, location); this.number = number; } - NumberNode(double number) { - super(TokenStream.NUMBER); + NumberNode(double number, CodePosition position) { + super(TokenStream.NUMBER, position); this.number = number; } @@ -61,19 +61,13 @@ public class Node implements Cloneable { return this.number; } - @Override - public boolean equals(Object o) { - return o instanceof NumberNode - && getDouble() == ((NumberNode) o).getDouble(); - } - private double number; } private static class StringNode extends Node { - StringNode(int type, String str) { - super(type); + StringNode(int type, String str, CodePosition position) { + super(type, position); if (null == str) { throw new IllegalArgumentException("StringNode: str is null"); } @@ -99,13 +93,6 @@ public class Node implements Cloneable { this.str = str; } - @Override - public boolean equals(Object o) { - if (!(o instanceof StringNode)) { return false; } - return o instanceof StringNode - && this.str.equals(((StringNode) o).str); - } - private String str; } @@ -113,30 +100,46 @@ public class Node implements Cloneable { type = nodeType; } - public Node(int nodeType, Node child) { + public Node(int nodeType, Node child, CodePosition position) { type = nodeType; first = last = child; child.next = null; + this.position = position; } - public Node(int nodeType, Node left, Node right) { + public Node(int nodeType, Node child, int operation, CodePosition position) { + type = nodeType; + first = last = child; + child.next = null; + this.operation = operation; + this.position = position; + } + + public Node(int nodeType, Node left, Node right, CodePosition position) { + this(nodeType, left, right, -1, position); + } + + public Node(int nodeType, Node left, Node right, int operation, CodePosition position) { type = nodeType; first = left; last = right; left.next = right; right.next = null; + this.operation = operation; + this.position = position; } - public Node(int nodeType, Node left, Node mid, Node right) { + public Node(int nodeType, Node left, Node mid, Node right, CodePosition position) { type = nodeType; first = left; last = right; left.next = mid; mid.next = right; right.next = null; + this.position = position; } - public Node(int nodeType, Node left, Node mid, Node mid2, Node right) { + public Node(int nodeType, Node left, Node mid, Node mid2, Node right, CodePosition position) { type = nodeType; first = left; last = right; @@ -144,6 +147,7 @@ public class Node implements Cloneable { mid.next = mid2; mid2.next = right; right.next = null; + this.position = position; } public Node(int nodeType, Node[] children) { @@ -166,40 +170,31 @@ public class Node implements Cloneable { } } - public Node(int nodeType, int value) { + public Node(int nodeType, CodePosition position) { type = nodeType; - intDatum = value; + this.position = position; } - public Node(int nodeType, Node child, int value) { - this(nodeType, child); - intDatum = value; + public Node(int nodeType, int operation, CodePosition position) { + type = nodeType; + this.operation = operation; + this.position = position; } - public Node(int nodeType, Node left, Node right, int value) { - this(nodeType, left, right); - intDatum = value; + public static Node newNumber(int number, CodePosition position) { + return new NumberNode(number, position); } - public Node(int nodeType, Node left, Node mid, Node right, int value) { - this(nodeType, left, mid, right); - intDatum = value; + public static Node newNumber(double number, CodePosition position) { + return new NumberNode(number, position); } - public static Node newNumber(int number) { - return new NumberNode(number); + public static Node newString(String str, CodePosition position) { + return new StringNode(TokenStream.STRING, str, position); } - public static Node newNumber(double number) { - return new NumberNode(number); - } - - public static Node newString(String str) { - return new StringNode(TokenStream.STRING, str); - } - - public static Node newString(int type, String str) { - return new StringNode(type, str); + public static Node newString(int type, String str, CodePosition position) { + return new StringNode(type, str, position); } public int getType() { @@ -210,10 +205,6 @@ public class Node implements Cloneable { this.type = type; } - public int getIntDatum() { - return this.intDatum; - } - public Node getFirstChild() { return first; } @@ -353,73 +344,12 @@ public class Node implements Cloneable { return null; } - public Object getProp(int propType) { - if (props == null) - return null; - return props.getObject(propType); - } - - public void putProp(int propType, Object prop) { - if (prop == null) { - removeProp(propType); - } - else { - if (props == null) { - props = new UintMap(2); - } - props.put(propType, prop); - } - } - - public void putIntProp(int propType, int prop) { - if (props == null) - props = new UintMap(2); - props.put(propType, prop); - } - - public void removeProp(int propType) { - if (props != null) { - props.remove(propType); - } - } - public int getOperation() { - switch (type) { - case TokenStream.EQOP: - case TokenStream.RELOP: - case TokenStream.UNARYOP: - case TokenStream.PRIMARY: - return intDatum; - } - Context.codeBug(); - return 0; + return operation; } - public int getLineno() { - if (hasLineno()) { - return intDatum; - } - return -1; - } - - private boolean hasLineno() { - switch (type) { - case TokenStream.EXPRSTMT: - case TokenStream.BLOCK: - case TokenStream.VAR: - case TokenStream.WHILE: - case TokenStream.DO: - case TokenStream.SWITCH: - case TokenStream.CATCH: - case TokenStream.THROW: - case TokenStream.RETURN: - case TokenStream.BREAK: - case TokenStream.CONTINUE: - case TokenStream.WITH: - case TokenStream.IF: - return true; - } - return false; + public CodePosition getPosition() { + return position; } /** Can only be called when getType() == TokenStream.NUMBER */ @@ -437,22 +367,6 @@ public class Node implements Cloneable { throw new UnsupportedOperationException(this + " is not a string node"); } - /** - * Not usefully implemented. - */ - @Override - public final int hashCode() { - assert false : "hashCode not designed"; - return 42; // any arbitrary constant will do - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Node)) { return false; } - return hasLineno() - || this.getIntDatum() == ((Node) o).getIntDatum(); - } - @Override public String toString() { if (Context.printTrees) { @@ -480,57 +394,19 @@ public class Node implements Cloneable { break; } } - if (intDatum != -1) { + if (operation != -1) { sb.append(' '); - sb.append(intDatum); - } - if (props == null) - return sb.toString(); - - int[] keys = props.getKeys(); - for (int i = 0; i != keys.length; ++i) { - int key = keys[i]; - sb.append(" ["); - sb.append(propToString(key)); - sb.append(": "); - switch (key) { - case FIXUPS_PROP : // can't add this as it recurses - sb.append("fixups property"); - break; - case SOURCE_PROP : // can't add this as it has unprintables - sb.append("source property"); - break; - case TARGETBLOCK_PROP : // can't add this as it recurses - sb.append("target block property"); - break; - case LASTUSE_PROP : // can't add this as it is dull - sb.append("last use property"); - break; - default : - Object obj = props.getObject(key); - if (obj != null) { - sb.append(obj.toString()); - } else { - sb.append(props.getExistingInt(key)); - } - break; - } - sb.append(']'); + sb.append(operation); } return sb.toString(); } return null; } - public void setIsSyntheticBlock(boolean val) { - isSyntheticBlock = val; - } - int type; // type of the node; TokenStream.NAME for example Node next; // next sibling private Node first; // first element of a linked list of children private Node last; // last element of a linked list of children - private int intDatum = -1; // encapsulated int data; depends on type - private UintMap props; - private boolean isSyntheticBlock = false; + private CodePosition position; + private int operation; } diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java index 72e23997b5b..e7b8b190cb4 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java @@ -86,19 +86,17 @@ public class Parser extends Observable { * will be returned. (The parse failure will result in a call to the current * Context's ErrorReporter.) */ - public Object parse(TokenStream ts) throws IOException { + public Node parse(TokenStream ts) throws IOException { this.ok = true; sourceTop = 0; functionNumber = 0; int tt; // last token from getToken(); - int baseLineno = ts.getLineno(); // line number where source starts /* * so we have something to add nodes to until we've collected all the source */ - Object tempBlock = nf.createLeaf(TokenStream.BLOCK); - ((Node) tempBlock).setIsSyntheticBlock(true); + Node tempBlock = nf.createLeaf(TokenStream.BLOCK, ts.tokenPosition); while (true) { ts.flags |= TokenStream.TSF_REGEXP; @@ -111,7 +109,7 @@ public class Parser extends Observable { if (tt == TokenStream.FUNCTION) { try { - nf.addChildToBack(tempBlock, function(ts, false)); + tempBlock.addChildToBack(function(ts, false)); } catch (JavaScriptException e) { this.ok = false; @@ -120,7 +118,7 @@ public class Parser extends Observable { } else { ts.ungetToken(tt); - nf.addChildToBack(tempBlock, statement(ts)); + tempBlock.addChildToBack(statement(ts)); } } @@ -129,9 +127,7 @@ public class Parser extends Observable { return null; } - Object pn = nf.createScript(tempBlock, ts.getSourceName(), baseLineno, ts.getLineno(), null); - ((Node) pn).setIsSyntheticBlock(true); - return pn; + return nf.createScript(tempBlock); } /* @@ -139,21 +135,21 @@ public class Parser extends Observable { * to be needed for tree generation... it'd only be useful for checking * argument hiding, which I'm not doing anyway... */ - private Object parseFunctionBody(TokenStream ts) throws IOException { + private Node parseFunctionBody(TokenStream ts) throws IOException { int oldflags = ts.flags; ts.flags &= ~(TokenStream.TSF_RETURN_EXPR | TokenStream.TSF_RETURN_VOID); ts.flags |= TokenStream.TSF_FUNCTION; - Object pn = nf.createBlock(ts.getLineno()); + Node pn = nf.createBlock(ts.tokenPosition); try { int tt; while ((tt = ts.peekToken()) > TokenStream.EOF && tt != TokenStream.RC) { if (tt == TokenStream.FUNCTION) { ts.getToken(); - nf.addChildToBack(pn, function(ts, false)); + pn.addChildToBack(function(ts, false)); } else { - nf.addChildToBack(pn, statement(ts)); + pn.addChildToBack(statement(ts)); } } } @@ -170,31 +166,30 @@ public class Parser extends Observable { return pn; } - private Object function(TokenStream ts, boolean isExpr) throws IOException, JavaScriptException { + private Node function(TokenStream ts, boolean isExpr) throws IOException, JavaScriptException { notifyObservers(new ParserEvents.OnFunctionParsingStart()); - int baseLineno = ts.getLineno(); // line number where source starts + CodePosition basePosition = ts.tokenPosition; - String name; - Object memberExprNode = null; + Node nameNode; + Node memberExprNode = null; if (ts.matchToken(TokenStream.NAME)) { - name = ts.getString(); + nameNode = nf.createName(ts.getString(), basePosition); if (!ts.matchToken(TokenStream.LP)) { if (Context.getContext().hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) { // Extension to ECMA: if 'function ' does not follow // by '(', assume starts memberExpr - Object memberExprHead = nf.createName(name); - name = null; - memberExprNode = memberExprTail(ts, false, memberExprHead); + Node memberExprHead = nameNode; + nameNode = null; + memberExprNode = memberExprTail(ts, false, memberExprHead, basePosition); } mustMatchToken(ts, TokenStream.LP, "msg.no.paren.parms"); } } else if (ts.matchToken(TokenStream.LP)) { // Anonymous function - name = null; + nameNode = null; } else { - name = null; if (Context.getContext().hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) { // Note that memberExpr can not start with '(' like // in (1+2).toString, because 'function (' already @@ -202,6 +197,7 @@ public class Parser extends Observable { memberExprNode = memberExpr(ts, false); } mustMatchToken(ts, TokenStream.LP, "msg.no.paren.parms"); + nameNode = null; } ++functionNumber; @@ -210,17 +206,18 @@ public class Parser extends Observable { // function to parent source int savedSourceTop = sourceTop; int savedFunctionNumber = functionNumber; - Object args; - Object body; + Node args; + Node body; try { functionNumber = 0; - args = nf.createLeaf(TokenStream.LP); + args = nf.createLeaf(TokenStream.LP, ts.tokenPosition); if (!ts.matchToken(TokenStream.GWT)) { do { + CodePosition namePosition = ts.tokenPosition; mustMatchToken(ts, TokenStream.NAME, "msg.no.parm"); String s = ts.getString(); - nf.addChildToBack(args, nf.createName(s)); + args.addChildToBack(nf.createName(s, namePosition)); } while (ts.matchToken(TokenStream.COMMA)); @@ -237,10 +234,9 @@ public class Parser extends Observable { functionNumber = savedFunctionNumber; } - Object pn = nf.createFunction(name, args, body, ts.getSourceName(), - baseLineno, ts.getLineno(), null, isExpr || memberExprNode != null); + Node pn = nf.createFunction(nameNode, args, body, basePosition); if (memberExprNode != null) { - pn = nf.createBinary(TokenStream.ASSIGN, TokenStream.NOP, memberExprNode, pn); + pn = nf.createBinary(TokenStream.ASSIGN, TokenStream.NOP, memberExprNode, pn, basePosition); } // Add EOL but only if function is not part of expression, in which @@ -253,19 +249,19 @@ public class Parser extends Observable { return pn; } - private Object statements(TokenStream ts) throws IOException { - Object pn = nf.createBlock(ts.getLineno()); + private Node statements(TokenStream ts) throws IOException { + Node pn = nf.createBlock(ts.tokenPosition); int tt; while ((tt = ts.peekToken()) > TokenStream.EOF && tt != TokenStream.RC) { - nf.addChildToBack(pn, statement(ts)); + pn.addChildToBack(statement(ts)); } return pn; } - private Object condition(TokenStream ts) throws IOException, JavaScriptException { - Object pn; + private Node condition(TokenStream ts) throws IOException, JavaScriptException { + Node pn; mustMatchToken(ts, TokenStream.LP, "msg.no.paren.cond"); pn = expr(ts, false); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.cond"); @@ -297,7 +293,8 @@ public class Parser extends Observable { } // match a NAME; return null if no match. - private String matchLabel(TokenStream ts) throws IOException, JavaScriptException { + private Node matchLabel(TokenStream ts) throws IOException, JavaScriptException { + CodePosition position = ts.tokenPosition; int lineno = ts.getLineno(); String label = null; @@ -312,23 +309,23 @@ public class Parser extends Observable { wellTerminated(ts, TokenStream.ERROR); } - return label; + return label != null ? nf.createString(label, position) : null; } - private Object statement(TokenStream ts) throws IOException { + private Node statement(TokenStream ts) throws IOException { + CodePosition position = ts.lastPosition; try { return statementHelper(ts); } catch (JavaScriptException e) { // skip to end of statement - int lineno = ts.getLineno(); int t; do { t = ts.getToken(); } while (t != TokenStream.SEMI && t != TokenStream.EOL && t != TokenStream.EOF && t != TokenStream.ERROR); - return nf.createExprStatement(nf.createName("error"), lineno); + return nf.createExprStatement(nf.createName("error", position), position); } } @@ -337,47 +334,47 @@ public class Parser extends Observable { * implemented. */ - private Object statementHelper(TokenStream ts) throws IOException, JavaScriptException { - Object pn; + private Node statementHelper(TokenStream ts) throws IOException, JavaScriptException { + Node pn; int tt; int lastExprType; // For wellTerminated tt = ts.getToken(); + CodePosition position = ts.tokenPosition; switch (tt) { case TokenStream.IF: { - int lineno = ts.getLineno(); - Object cond = condition(ts); - Object ifTrue = statement(ts); - Object ifFalse = null; + Node cond = condition(ts); + Node ifTrue = statement(ts); + Node ifFalse = null; if (ts.matchToken(TokenStream.ELSE)) { ifFalse = statement(ts); } - pn = nf.createIf(cond, ifTrue, ifFalse, lineno); + pn = nf.createIf(cond, ifTrue, ifFalse, position); break; } case TokenStream.SWITCH: { - pn = nf.createSwitch(ts.getLineno()); + pn = nf.createSwitch(position); - Object cur_case = null; // to kill warning - Object case_statements; + Node curCase = null; // to kill warning + Node caseStatements; mustMatchToken(ts, TokenStream.LP, "msg.no.paren.switch"); - nf.addChildToBack(pn, expr(ts, false)); + pn.addChildToBack(expr(ts, false)); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.switch"); mustMatchToken(ts, TokenStream.LC, "msg.no.brace.switch"); while ((tt = ts.getToken()) != TokenStream.RC && tt != TokenStream.EOF) { switch (tt) { case TokenStream.CASE: - cur_case = nf.createUnary(TokenStream.CASE, expr(ts, false)); + curCase = nf.createUnary(TokenStream.CASE, expr(ts, false), ts.tokenPosition); break; case TokenStream.DEFAULT: - cur_case = nf.createLeaf(TokenStream.DEFAULT); + curCase = nf.createLeaf(TokenStream.DEFAULT, ts.tokenPosition); // XXX check that there isn't more than one default break; @@ -387,60 +384,56 @@ public class Parser extends Observable { } mustMatchToken(ts, TokenStream.COLON, "msg.no.colon.case"); - case_statements = nf.createLeaf(TokenStream.BLOCK); - ((Node) case_statements).setIsSyntheticBlock(true); + caseStatements = nf.createLeaf(TokenStream.BLOCK, null); while ((tt = ts.peekToken()) != TokenStream.RC && tt != TokenStream.CASE && tt != TokenStream.DEFAULT && tt != TokenStream.EOF) { - nf.addChildToBack(case_statements, statement(ts)); + caseStatements.addChildToBack(statement(ts)); } // assert cur_case - nf.addChildToBack(cur_case, case_statements); + if (curCase != null) { + curCase.addChildToBack(caseStatements); + } - nf.addChildToBack(pn, cur_case); + pn.addChildToBack(curCase); } break; } case TokenStream.WHILE: { - int lineno = ts.getLineno(); - Object cond = condition(ts); - Object body = statement(ts); + Node cond = condition(ts); + Node body = statement(ts); - pn = nf.createWhile(cond, body, lineno); + pn = nf.createWhile(cond, body, position); break; } case TokenStream.DO: { - int lineno = ts.getLineno(); - - Object body = statement(ts); + Node body = statement(ts); mustMatchToken(ts, TokenStream.WHILE, "msg.no.while.do"); - Object cond = condition(ts); + Node cond = condition(ts); - pn = nf.createDoWhile(body, cond, lineno); + pn = nf.createDoWhile(body, cond, position); break; } case TokenStream.FOR: { - int lineno = ts.getLineno(); - - Object init; // Node init is also foo in 'foo in Object' - Object cond; // Node cond is also object in 'foo in Object' - Object incr = null; // to kill warning - Object body; + Node init; // Node init is also foo in 'foo in Object' + Node cond; // Node cond is also object in 'foo in Object' + Node incr = null; // to kill warning + Node body; mustMatchToken(ts, TokenStream.LP, "msg.no.paren.for"); tt = ts.peekToken(); if (tt == TokenStream.SEMI) { - init = nf.createLeaf(TokenStream.VOID); + init = nf.createLeaf(TokenStream.VOID, null); } else { if (tt == TokenStream.VAR) { // set init to a var list or initial ts.getToken(); // throw away the 'var' token - init = variables(ts, true); + init = variables(ts, true, ts.tokenPosition); } else { init = expr(ts, true); @@ -457,7 +450,7 @@ public class Parser extends Observable { mustMatchToken(ts, TokenStream.SEMI, "msg.no.semi.for"); if (ts.peekToken() == TokenStream.SEMI) { // no loop condition - cond = nf.createLeaf(TokenStream.VOID); + cond = nf.createLeaf(TokenStream.VOID, null); } else { cond = expr(ts, false); @@ -465,7 +458,7 @@ public class Parser extends Observable { mustMatchToken(ts, TokenStream.SEMI, "msg.no.semi.for.cond"); if (ts.peekToken() == TokenStream.GWT) { - incr = nf.createLeaf(TokenStream.VOID); + incr = nf.createLeaf(TokenStream.VOID, null); } else { incr = expr(ts, false); @@ -477,24 +470,22 @@ public class Parser extends Observable { if (incr == null) { // cond could be null if 'in obj' got eaten by the init node. - pn = nf.createForIn(init, cond, body, lineno); + pn = nf.createForIn(init, cond, body, position); } else { - pn = nf.createFor(init, cond, incr, body, lineno); + pn = nf.createFor(init, cond, incr, body, position); } break; } case TokenStream.TRY: { - int lineno = ts.getLineno(); - - Object tryblock; - Object catchblocks; - Object finallyblock = null; + Node tryblock; + Node catchblocks; + Node finallyblock = null; tryblock = statement(ts); - catchblocks = nf.createLeaf(TokenStream.BLOCK); + catchblocks = nf.createLeaf(TokenStream.BLOCK, null); boolean sawDefaultCatch = false; int peek = ts.peekToken(); @@ -503,12 +494,13 @@ public class Parser extends Observable { if (sawDefaultCatch) { reportError(ts, "msg.catch.unreachable"); } + CodePosition catchPosition = ts.tokenPosition; mustMatchToken(ts, TokenStream.LP, "msg.no.paren.catch"); mustMatchToken(ts, TokenStream.NAME, "msg.bad.catchcond"); - String varName = ts.getString(); + Node varName = nf.createName(ts.getString(), ts.tokenPosition); - Object catchCond = null; + Node catchCond = null; if (ts.matchToken(TokenStream.IF)) { catchCond = expr(ts, false); } @@ -519,7 +511,7 @@ public class Parser extends Observable { mustMatchToken(ts, TokenStream.GWT, "msg.bad.catchcond"); mustMatchToken(ts, TokenStream.LC, "msg.no.brace.catchblock"); - nf.addChildToBack(catchblocks, nf.createCatch(varName, catchCond, statements(ts), ts.getLineno())); + catchblocks.addChildToBack(nf.createCatch(varName, catchCond, statements(ts), catchPosition)); mustMatchToken(ts, TokenStream.RC, "msg.no.brace.after.body"); } @@ -532,37 +524,32 @@ public class Parser extends Observable { finallyblock = statement(ts); } - pn = nf.createTryCatchFinally(tryblock, catchblocks, finallyblock, lineno); + pn = nf.createTryCatchFinally(tryblock, catchblocks, finallyblock, position); break; } case TokenStream.THROW: { int lineno = ts.getLineno(); - pn = nf.createThrow(expr(ts, false), lineno); + pn = nf.createThrow(expr(ts, false), position); if (lineno == ts.getLineno()) { wellTerminated(ts, TokenStream.ERROR); } break; } case TokenStream.BREAK: { - int lineno = ts.getLineno(); - // matchLabel only matches if there is one - String label = matchLabel(ts); - pn = nf.createBreak(label, lineno); + Node label = matchLabel(ts); + pn = nf.createBreak(label, position); break; } case TokenStream.CONTINUE: { - int lineno = ts.getLineno(); - // matchLabel only matches if there is one - String label = matchLabel(ts); - pn = nf.createContinue(label, lineno); + Node label = matchLabel(ts); + pn = nf.createContinue(label, position); break; } case TokenStream.DEBUGGER: { - int lineno = ts.getLineno(); - pn = nf.createDebugger(lineno); + pn = nf.createDebugger(position); break; } case TokenStream.WITH: { @@ -572,25 +559,24 @@ public class Parser extends Observable { reportError(ts, "msg.jsni.unsupported.with"); - int lineno = ts.getLineno(); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.with"); - Object obj = expr(ts, false); + Node obj = expr(ts, false); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.with"); - Object body = statement(ts); - pn = nf.createWith(obj, body, lineno); + Node body = statement(ts); + pn = nf.createWith(obj, body, position); break; } case TokenStream.VAR: { int lineno = ts.getLineno(); - pn = variables(ts, false); + pn = variables(ts, false, position); if (ts.getLineno() == lineno) { wellTerminated(ts, TokenStream.ERROR); } break; } case TokenStream.RETURN: { - Object retExpr = null; - int lineno = 0; + Node retExpr = null; + int lineno; // bail if we're not in a (toplevel) function if ((!insideFunction) && ((ts.flags & TokenStream.TSF_FUNCTION) == 0)) { reportError(ts, "msg.bad.return"); @@ -614,7 +600,7 @@ public class Parser extends Observable { } // XXX ASSERT pn - pn = nf.createReturn(retExpr, lineno); + pn = nf.createReturn(retExpr, position); break; } case TokenStream.LC: @@ -626,7 +612,7 @@ public class Parser extends Observable { // Fall thru, to have a node for error recovery to work on case TokenStream.EOL: case TokenStream.SEMI: - pn = nf.createLeaf(TokenStream.VOID); + pn = nf.createLeaf(TokenStream.VOID, ts.tokenPosition); break; default: { @@ -653,12 +639,12 @@ public class Parser extends Observable { * follows: nf.addChildToBack(pn, statement(ts)); */ String name = ts.getString(); - pn = nf.createLabel(name, lineno); + pn = nf.createLabel(nf.createString(name, position), position); // bruce: added to make it easier to bind labels to the // statements they modify // - nf.addChildToBack(pn, statement(ts)); + pn.addChildToBack(statement(ts)); // depend on decompiling lookahead to guess that that // last name was a label. @@ -671,7 +657,7 @@ public class Parser extends Observable { } } - pn = nf.createExprStatement(pn, lineno); + pn = nf.createExprStatement(pn, position); /* * Check explicitly against (multi-line) function statement. @@ -693,15 +679,15 @@ public class Parser extends Observable { return pn; } - private Object variables(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = nf.createVariables(ts.getLineno()); + private Node variables(TokenStream ts, boolean inForInit, CodePosition position) throws IOException, JavaScriptException { + Node pn = nf.createVariables(position); while (true) { - Object name; - Object init; + Node name; + Node init; mustMatchToken(ts, TokenStream.NAME, "msg.bad.var"); String s = ts.getString(); - name = nf.createName(s); + name = nf.createName(s, ts.tokenPosition); // omitted check for argument hiding @@ -711,9 +697,9 @@ public class Parser extends Observable { } init = assignExpr(ts, inForInit); - nf.addChildToBack(name, init); + name.addChildToBack(init); } - nf.addChildToBack(pn, name); + pn.addChildToBack(name); if (!ts.matchToken(TokenStream.COMMA)) { break; } @@ -721,93 +707,90 @@ public class Parser extends Observable { return pn; } - private Object expr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = assignExpr(ts, inForInit); + private Node expr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = assignExpr(ts, inForInit); while (ts.matchToken(TokenStream.COMMA)) { - pn = nf.createBinary(TokenStream.COMMA, pn, assignExpr(ts, inForInit)); + pn = nf.createBinary(TokenStream.COMMA, pn, assignExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object assignExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = condExpr(ts, inForInit); + private Node assignExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = condExpr(ts, inForInit); if (ts.matchToken(TokenStream.ASSIGN)) { // omitted: "invalid assignment left-hand side" check. - pn = nf.createBinary(TokenStream.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit)); + pn = nf.createBinary(TokenStream.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object condExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object ifTrue; - Object ifFalse; - - Object pn = orExpr(ts, inForInit); + private Node condExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = orExpr(ts, inForInit); if (ts.matchToken(TokenStream.HOOK)) { - ifTrue = assignExpr(ts, false); + Node ifTrue = assignExpr(ts, false); mustMatchToken(ts, TokenStream.COLON, "msg.no.colon.cond"); - ifFalse = assignExpr(ts, inForInit); - return nf.createTernary(pn, ifTrue, ifFalse); + Node ifFalse = assignExpr(ts, inForInit); + return nf.createTernary(pn, ifTrue, ifFalse, pn.getPosition()); } return pn; } - private Object orExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = andExpr(ts, inForInit); - if (ts.matchToken(TokenStream.OR)) { - pn = nf.createBinary(TokenStream.OR, pn, orExpr(ts, inForInit)); + private Node orExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = andExpr(ts, inForInit); + while (ts.matchToken(TokenStream.OR)) { + pn = nf.createBinary(TokenStream.OR, pn, andExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object andExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = bitOrExpr(ts, inForInit); - if (ts.matchToken(TokenStream.AND)) { - pn = nf.createBinary(TokenStream.AND, pn, andExpr(ts, inForInit)); + private Node andExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = bitOrExpr(ts, inForInit); + while (ts.matchToken(TokenStream.AND)) { + pn = nf.createBinary(TokenStream.AND, pn, bitOrExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object bitOrExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = bitXorExpr(ts, inForInit); + private Node bitOrExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = bitXorExpr(ts, inForInit); while (ts.matchToken(TokenStream.BITOR)) { - pn = nf.createBinary(TokenStream.BITOR, pn, bitXorExpr(ts, inForInit)); + pn = nf.createBinary(TokenStream.BITOR, pn, bitXorExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object bitXorExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = bitAndExpr(ts, inForInit); + private Node bitXorExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = bitAndExpr(ts, inForInit); while (ts.matchToken(TokenStream.BITXOR)) { - pn = nf.createBinary(TokenStream.BITXOR, pn, bitAndExpr(ts, inForInit)); + pn = nf.createBinary(TokenStream.BITXOR, pn, bitAndExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object bitAndExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = eqExpr(ts, inForInit); + private Node bitAndExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = eqExpr(ts, inForInit); while (ts.matchToken(TokenStream.BITAND)) { - pn = nf.createBinary(TokenStream.BITAND, pn, eqExpr(ts, inForInit)); + pn = nf.createBinary(TokenStream.BITAND, pn, eqExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object eqExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = relExpr(ts, inForInit); + private Node eqExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = relExpr(ts, inForInit); while (ts.matchToken(TokenStream.EQOP)) { - pn = nf.createBinary(TokenStream.EQOP, ts.getOp(), pn, relExpr(ts, inForInit)); + pn = nf.createBinary(TokenStream.EQOP, ts.getOp(), pn, relExpr(ts, inForInit), pn.getPosition()); } return pn; } - private Object relExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { - Object pn = shiftExpr(ts); + private Node relExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { + Node pn = shiftExpr(ts); while (ts.matchToken(TokenStream.RELOP)) { int op = ts.getOp(); if (inForInit && op == TokenStream.IN) { @@ -815,66 +798,67 @@ public class Parser extends Observable { break; } - pn = nf.createBinary(TokenStream.RELOP, op, pn, shiftExpr(ts)); + pn = nf.createBinary(TokenStream.RELOP, op, pn, shiftExpr(ts), pn.getPosition()); } return pn; } - private Object shiftExpr(TokenStream ts) throws IOException, JavaScriptException { - Object pn = addExpr(ts); + private Node shiftExpr(TokenStream ts) throws IOException, JavaScriptException { + Node pn = addExpr(ts); while (ts.matchToken(TokenStream.SHOP)) { - pn = nf.createBinary(TokenStream.SHOP, ts.getOp(), pn, addExpr(ts)); + pn = nf.createBinary(TokenStream.SHOP, ts.getOp(), pn, addExpr(ts), pn.getPosition()); } return pn; } - private Object addExpr(TokenStream ts) throws IOException, JavaScriptException { + private Node addExpr(TokenStream ts) throws IOException, JavaScriptException { int tt; - Object pn = mulExpr(ts); + Node pn = mulExpr(ts); while ((tt = ts.getToken()) == TokenStream.ADD || tt == TokenStream.SUB) { // flushNewLines - pn = nf.createBinary(tt, pn, mulExpr(ts)); + pn = nf.createBinary(tt, pn, mulExpr(ts), pn.getPosition()); } ts.ungetToken(tt); return pn; } - private Object mulExpr(TokenStream ts) throws IOException, JavaScriptException { + private Node mulExpr(TokenStream ts) throws IOException, JavaScriptException { int tt; - Object pn = unaryExpr(ts); + Node pn = unaryExpr(ts); while ((tt = ts.peekToken()) == TokenStream.MUL || tt == TokenStream.DIV || tt == TokenStream.MOD) { tt = ts.getToken(); - pn = nf.createBinary(tt, pn, unaryExpr(ts)); + pn = nf.createBinary(tt, pn, unaryExpr(ts), pn.getPosition()); } return pn; } - private Object unaryExpr(TokenStream ts) throws IOException, JavaScriptException { + private Node unaryExpr(TokenStream ts) throws IOException, JavaScriptException { int tt; ts.flags |= TokenStream.TSF_REGEXP; tt = ts.getToken(); ts.flags &= ~TokenStream.TSF_REGEXP; + CodePosition position = ts.tokenPosition; switch (tt) { case TokenStream.UNARYOP: - return nf.createUnary(TokenStream.UNARYOP, ts.getOp(), unaryExpr(ts)); + return nf.createUnary(TokenStream.UNARYOP, ts.getOp(), unaryExpr(ts), position); case TokenStream.ADD: case TokenStream.SUB: - return nf.createUnary(TokenStream.UNARYOP, tt, unaryExpr(ts)); + return nf.createUnary(TokenStream.UNARYOP, tt, unaryExpr(ts), position); case TokenStream.INC: case TokenStream.DEC: - return nf.createUnary(tt, TokenStream.PRE, memberExpr(ts, true)); + return nf.createUnary(tt, TokenStream.PRE, memberExpr(ts, true), position); case TokenStream.DELPROP: - return nf.createUnary(TokenStream.DELPROP, unaryExpr(ts)); + return nf.createUnary(TokenStream.DELPROP, unaryExpr(ts), position); case TokenStream.ERROR: break; @@ -884,7 +868,7 @@ public class Parser extends Observable { int lineno = ts.getLineno(); - Object pn = memberExpr(ts, true); + Node pn = memberExpr(ts, true); /* * don't look across a newline boundary for a postfix incop. @@ -897,21 +881,21 @@ public class Parser extends Observable { if (((peeked = ts.peekToken()) == TokenStream.INC || peeked == TokenStream.DEC) && ts.getLineno() == lineno) { int pf = ts.getToken(); - return nf.createUnary(pf, TokenStream.POST, pn); + return nf.createUnary(pf, TokenStream.POST, pn, position); } return pn; } - return nf.createName("err"); // Only reached on error. Try to continue. + return nf.createName("err", position); // Only reached on error. Try to continue. } - private Object argumentList(TokenStream ts, Object listNode) throws IOException, JavaScriptException { + private Node argumentList(TokenStream ts, Node listNode) throws IOException, JavaScriptException { boolean matched; ts.flags |= TokenStream.TSF_REGEXP; matched = ts.matchToken(TokenStream.GWT); ts.flags &= ~TokenStream.TSF_REGEXP; if (!matched) { do { - nf.addChildToBack(listNode, assignExpr(ts, false)); + listNode.addChildToBack(assignExpr(ts, false)); } while (ts.matchToken(TokenStream.COMMA)); @@ -920,10 +904,11 @@ public class Parser extends Observable { return listNode; } - private Object memberExpr(TokenStream ts, boolean allowCallSyntax) throws IOException, JavaScriptException { + private Node memberExpr(TokenStream ts, boolean allowCallSyntax) throws IOException, JavaScriptException { int tt; - Object pn; + Node pn; + CodePosition position = ts.tokenPosition; /* Check for new expressions. */ ts.flags |= TokenStream.TSF_REGEXP; @@ -934,8 +919,8 @@ public class Parser extends Observable { ts.getToken(); /* Make a NEW node to append to. */ - pn = nf.createLeaf(TokenStream.NEW); - nf.addChildToBack(pn, memberExpr(ts, false)); + pn = nf.createLeaf(TokenStream.NEW, position); + pn.addChildToBack(memberExpr(ts, false)); if (ts.matchToken(TokenStream.LP)) { /* Add the arguments to pn, if any are supplied. */ @@ -955,19 +940,19 @@ public class Parser extends Observable { */ tt = ts.peekToken(); if (tt == TokenStream.LC) { - nf.addChildToBack(pn, primaryExpr(ts)); + pn.addChildToBack(primaryExpr(ts)); } } else { pn = primaryExpr(ts); } - return memberExprTail(ts, allowCallSyntax, pn); + return memberExprTail(ts, allowCallSyntax, pn, position); } - private Object memberExprTail( + private Node memberExprTail( TokenStream ts, boolean allowCallSyntax, - Object pn + Node pn, CodePosition position ) throws IOException, JavaScriptException { lastExprEndLine = ts.getLineno(); int tt; @@ -976,7 +961,7 @@ public class Parser extends Observable { ts.treatKeywordAsIdentifier = true; mustMatchToken(ts, TokenStream.NAME, "msg.no.name.after.dot"); ts.treatKeywordAsIdentifier = false; - pn = nf.createBinary(TokenStream.DOT, pn, nf.createName(ts.getString())); + pn = nf.createBinary(TokenStream.DOT, pn, nf.createName(ts.getString(), ts.tokenPosition), position); /* * pn = nf.createBinary(ts.DOT, pn, memberExpr(ts)) is the version in * Brendan's IR C version. Not in ECMA... does it reflect the 'new' @@ -985,14 +970,14 @@ public class Parser extends Observable { lastExprEndLine = ts.getLineno(); } else if (tt == TokenStream.LB) { - pn = nf.createBinary(TokenStream.LB, pn, expr(ts, false)); + pn = nf.createBinary(TokenStream.LB, pn, expr(ts, false), position); mustMatchToken(ts, TokenStream.RB, "msg.no.bracket.index"); lastExprEndLine = ts.getLineno(); } else if (allowCallSyntax && tt == TokenStream.LP) { /* make a call node */ - pn = nf.createUnary(TokenStream.CALL, pn); + pn = nf.createUnary(TokenStream.CALL, pn, position); /* Add the arguments to pn, if any are supplied. */ pn = argumentList(ts, pn); @@ -1007,13 +992,14 @@ public class Parser extends Observable { return pn; } - public Object primaryExpr(TokenStream ts) throws IOException, JavaScriptException { + public Node primaryExpr(TokenStream ts) throws IOException, JavaScriptException { int tt; - Object pn; + Node pn; ts.flags |= TokenStream.TSF_REGEXP; tt = ts.getToken(); + CodePosition position = ts.tokenPosition; ts.flags &= ~TokenStream.TSF_REGEXP; switch (tt) { @@ -1022,7 +1008,7 @@ public class Parser extends Observable { return function(ts, true); case TokenStream.LB: { - pn = nf.createLeaf(TokenStream.ARRAYLIT); + pn = nf.createLeaf(TokenStream.ARRAYLIT, position); ts.flags |= TokenStream.TSF_REGEXP; boolean matched = ts.matchToken(TokenStream.RB); @@ -1039,10 +1025,10 @@ public class Parser extends Observable { } if (tt == TokenStream.COMMA) { - nf.addChildToBack(pn, nf.createLeaf(TokenStream.PRIMARY, TokenStream.UNDEFINED)); + pn.addChildToBack(nf.createLeaf(TokenStream.PRIMARY, TokenStream.UNDEFINED, position)); } else { - nf.addChildToBack(pn, assignExpr(ts, false)); + pn.addChildToBack(assignExpr(ts, false)); } } while (ts.matchToken(TokenStream.COMMA)); @@ -1053,28 +1039,28 @@ public class Parser extends Observable { } case TokenStream.LC: { - pn = nf.createLeaf(TokenStream.OBJLIT); + pn = nf.createLeaf(TokenStream.OBJLIT, position); if (!ts.matchToken(TokenStream.RC)) { commaloop: do { - Object property; + Node property; tt = ts.getToken(); switch (tt) { // map NAMEs to STRINGs in object literal context. case TokenStream.NAME: case TokenStream.STRING: - property = nf.createString(ts.getString()); + property = nf.createString(ts.getString(), ts.tokenPosition); break; case TokenStream.NUMBER_INT: int n = (int) ts.getNumber(); - property = nf.createNumber(n); + property = nf.createNumber(n, ts.tokenPosition); break; case TokenStream.NUMBER: double d = ts.getNumber(); - property = nf.createNumber(d); + property = nf.createNumber(d, ts.tokenPosition); break; case TokenStream.RC: // trailing comma is OK. @@ -1088,8 +1074,8 @@ public class Parser extends Observable { // OBJLIT is used as ':' in object literal for // decompilation to solve spacing ambiguity. - nf.addChildToBack(pn, property); - nf.addChildToBack(pn, assignExpr(ts, false)); + pn.addChildToBack(property); + pn.addChildToBack(assignExpr(ts, false)); } while (ts.matchToken(TokenStream.COMMA)); @@ -1112,29 +1098,29 @@ public class Parser extends Observable { case TokenStream.NAME: String name = ts.getString(); - return nf.createName(name); + return nf.createName(name, position); case TokenStream.NUMBER_INT: int n = (int) ts.getNumber(); - return nf.createNumber(n); + return nf.createNumber(n, position); case TokenStream.NUMBER: double d = ts.getNumber(); - return nf.createNumber(d); + return nf.createNumber(d, position); case TokenStream.STRING: String s = ts.getString(); - return nf.createString(s); + return nf.createString(s, position); case TokenStream.REGEXP: { String flags = ts.regExpFlags; ts.regExpFlags = null; String re = ts.getString(); - return nf.createRegExp(re, flags); + return nf.createRegExp(re, flags, position); } case TokenStream.PRIMARY: - return nf.createLeaf(TokenStream.PRIMARY, ts.getOp()); + return nf.createLeaf(TokenStream.PRIMARY, ts.getOp(), position); case TokenStream.ERROR: /* the scanner or one of its subroutines reported the error. */ diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java index c52b98e2592..8464f7fba2f 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java @@ -514,8 +514,7 @@ public class TokenStream { return true; // didn't match, push back token - tokenno--; - this.pushbackToken = token; + ungetToken(token); return false; } @@ -526,6 +525,8 @@ public class TokenStream { throw new RuntimeException(message); } this.pushbackToken = tt; + lastPosition = secondToLastPosition; + lastTokenPosition = tokenPosition; tokenno--; } @@ -533,6 +534,8 @@ public class TokenStream { int result = getToken(); this.pushbackToken = result; + lastPosition = secondToLastPosition; + lastTokenPosition = tokenPosition; tokenno--; return result; } @@ -583,13 +586,14 @@ public class TokenStream { } public int getToken() throws IOException { - int c; - do { - c = getTokenHelper(); - } while (c == RETRY_TOKEN); + lastTokenPosition = tokenPosition; + int c; + do { + c = getTokenHelper(); + } while (c == RETRY_TOKEN); - updatePosition(); - return c; + updatePosition(); + return c; } private int getTokenHelper() throws IOException { @@ -613,6 +617,7 @@ public class TokenStream { } } while (isJSSpace(c) || c == '\n'); + tokenPosition = new CodePosition(in.getLineno(), Math.max(in.getOffset() - 1, 0)); if (c == EOF_CHAR) return EOF; if (c != '-' && c != '\n') @@ -694,7 +699,7 @@ public class TokenStream { } in.unread(); - String str = getStringFromBuffer(); + String str = getStringFromBuffer(); if (!containsEscape && !treatKeywordAsIdentifier) { // OPT we shouldn't have to make a string (object!) to // check if it's a keyword. @@ -1475,6 +1480,8 @@ public class TokenStream { CodePosition secondToLastPosition; CodePosition lastPosition; + CodePosition tokenPosition; + CodePosition lastTokenPosition; private int op; public boolean treatKeywordAsIdentifier;