package otto import ( "regexp" ) func (self *_parser) ParsePrimaryExpression() _node { token := self.Peek() switch token.Kind { case "identifier": return self.ConsumeIdentifier() case "string": return self.ConsumeString() case "boolean": return self.ConsumeBoolean() case "number": return self.ConsumeNumber() case "null": return self.ConsumeNull() case "function": return self.ParseFunction(false) case "this": self.Next() return newThisNode() case "{": return self.ParseObjectLiteral() case "[": return self.ParseArrayLiteral() case "(": self.Expect("(") result := self.ParseExpression() self.Expect(")") return result case "/", "/=": // Here, "/" & "/=" actually indicate // the beginning of a regular expression return self.ParseRegExpLiteral(token) } panic(self.Unexpected(token)) } func (self *_parser) ParseObjectPropertyKey() string { if self.Match("identifier") { return self.ConsumeIdentifier().Value } else if self.Match("number") { return toString(self.ConsumeNumber().Value) } else if self.Match("string") { return toString(self.ConsumeString().Value) } panic(self.Unexpected(self.Peek())) } func (self *_parser) ParseObjectProperty() *_objectPropertyNode { key := self.ParseObjectPropertyKey() self.Expect(":") value := self.ParseAssignmentExpression() return newObjectPropertyNode(key, value) } func (self *_parser) ParseRegExpLiteral(token _token) *_regExpNode { pattern := self.ScanRegularExpression().Text flags := "" if self.Match("identifier") { // gim flags = self.Consume() } pattern_ := transformRegExp(pattern) _, err := regexp.Compile(pattern_) if err != nil { panic(token.newSyntaxError("Invalid regular expression")) } return newRegExpNode(pattern_, flags) } func (self *_parser) ParseObjectLiteral() *_objectNode { node := newObjectNode() self.Expect("{") for !self.Match("}") { property := self.ParseObjectProperty() node.AddProperty(property) if self.Accept(",") { continue } } self.Expect("}") return node } func (self *_parser) ParseArrayValue() _node { return self.ParseAssignmentExpression() } func (self *_parser) ParseArrayLiteral() *_arrayNode { self.Expect("[") nodeList := []_node{} for !self.Match("]") { nodeList = append(nodeList, self.ParseArrayValue()) if self.Accept(",") { continue } } self.Expect("]") return newArrayNode(nodeList) } func (self *_parser) ParseArgumentList() (argumentList []_node) { self.Expect("(") if !self.Match(")") { argumentList = make([]_node, 0) for { argumentList = append(argumentList, self.ParseAssignmentExpression()) if !self.Accept(",") { break } } } self.Expect(")") return argumentList } func (self *_parser) ParseCallExpression(left _node) _node { left = newCallNode(left) left.(*_callNode).ArgumentList = self.ParseArgumentList() return left } func (self *_parser) ParseDotMember(left _node) _node { self.Expect(".") member := self.ConsumeIdentifier().Value return newDotMemberNode(left, member) } func (self *_parser) ParseBracketMember(left _node) _node { self.Expect("[") member := self.ParseExpression() self.Expect("]") return newBracketMemberNode(left, member) } func (self *_parser) ParseNewExpression() _node { self.Expect("new") node := newnewNode(self.ParseLeftHandSideExpression()) if self.Match("(") { node.ArgumentList = self.ParseArgumentList() } return node } func (self *_parser) ParseLeftHandSideExpression() _node { var left _node if self.Match("new") { left = self.ParseNewExpression() } else { left = self.ParsePrimaryExpression() } for { if self.Match(".") { left = self.ParseDotMember(left) } else if self.Match("[") { left = self.ParseBracketMember(left) } else { break } } return left } func (self *_parser) ParseLeftHandSideExpressionAllowCall() _node { var left _node if self.Match("new") { left = self.ParseNewExpression() } else { left = self.ParsePrimaryExpression() } for { if self.Match(".") { left = self.ParseDotMember(left) } else if self.Match("[") { left = self.ParseBracketMember(left) } else if self.Match("(") { left = self.ParseCallExpression(left) } else { break } } return left } func (self *_parser) ParsePostfixExpression() _node { left := self.ParseLeftHandSideExpressionAllowCall() // TODO Need better syntax checking here // Strictness checking, etc. switch token := self.Peek(); token.Kind { case "++", "--": // Postfix, either =++ or =-- if self.Match("\n") { // TODO Why? break } switch left.Type() { case nodeIdentifier, nodeDotMember, nodeBracketMember: default: panic(self.History(-1).newSyntaxError("Invalid left-hand side in assignment")) } return newUnaryOperationNode("=" + self.Consume(), left) } return left } func (self *_parser) ParseUnaryExpression() _node { // TODO Need better syntax checking here // Strictness checking, basically (trying to delete a non-reference, etc.) switch token := self.Peek(); token.Kind { case "+", "-", "!", "~": return newUnaryOperationNode(self.Consume(), self.ParseUnaryExpression()) case "++", "--": // Prefix, either ++= or --= operation := self.Consume() left := self.ParseUnaryExpression() switch left.Type() { case nodeIdentifier, nodeDotMember, nodeBracketMember: default: panic(self.History(-1).newSyntaxError("Invalid left-hand side in assignment")) } return newUnaryOperationNode(operation + "=", left) case "delete", "void", "typeof": return newUnaryOperationNode(self.Consume(), self.ParseUnaryExpression()) } return self.ParsePostfixExpression() } func (self *_parser) ParseMultiplicativeExpression() _node { left := self.ParseUnaryExpression() REPEAT: switch self.Peek().Kind { case "*", "/", "%": left = newBinaryOperationNode(self.Consume(), left, self.ParseUnaryExpression()) goto REPEAT } return left } func (self *_parser) ParseAdditiveExpression() _node { left := self.ParseMultiplicativeExpression() REPEAT: switch self.Peek().Kind { case "+", "-": left = newBinaryOperationNode(self.Consume(), left, self.ParseMultiplicativeExpression()) goto REPEAT } return left } func (self *_parser) ParseShiftExpression() _node { left := self.ParseAdditiveExpression() REPEAT: switch self.Peek().Kind { case "<<", ">>", ">>>": left = newBinaryOperationNode(self.Consume(), left, self.ParseAdditiveExpression()) goto REPEAT } return left } func (self *_parser) ParseRelationalExpression() _node { previousAllowIn := self.Scope().AllowIn self.Scope().AllowIn = true left := self.ParseShiftExpression() self.Scope().AllowIn = previousAllowIn // TODO This should be deferred switch self.Peek().Kind { case "<", ">", "<=", ">=": return newComparisonNode(self.Consume(), left, self.ParseRelationalExpression()) case "instanceof": return newBinaryOperationNode(self.Consume(), left, self.ParseRelationalExpression()) case "in": if !self.Scope().AllowIn { return left } return newBinaryOperationNode(self.Consume(), left, self.ParseRelationalExpression()) } return left } func (self *_parser) ParseEqualityExpression() _node { left := self.ParseRelationalExpression() REPEAT: switch self.Peek().Kind { case "==", "!=", "===", "!==": left = newComparisonNode(self.Consume(), left, self.ParseRelationalExpression()) goto REPEAT } return left } func (self *_parser) ParseBitwiseANDExpression() _node { left := self.ParseEqualityExpression() for self.Match("&") { left = newBinaryOperationNode(self.Consume(), left, self.ParseEqualityExpression()) } return left } func (self *_parser) ParseBitwiseXORExpression() _node { left := self.ParseBitwiseANDExpression() for self.Match("^") { left = newBinaryOperationNode(self.Consume(), left, self.ParseBitwiseANDExpression()) } return left } func (self *_parser) ParseBitwiseORExpression() _node { left := self.ParseBitwiseXORExpression() for self.Match("|") { left = newBinaryOperationNode(self.Consume(), left, self.ParseBitwiseXORExpression()) } return left } func (self *_parser) ParseLogicalANDExpression() _node { left := self.ParseBitwiseORExpression() for self.Match("&&") { left = newBinaryOperationNode(self.Consume(), left, self.ParseBitwiseORExpression()) } return left } func (self *_parser) ParseLogicalORExpression() _node { left := self.ParseLogicalANDExpression() for self.Match("||") { left = newBinaryOperationNode(self.Consume(), left, self.ParseLogicalANDExpression()) } return left } func (self *_parser) ParseConditionlExpression() _node { left := self.ParseLogicalORExpression() if self.Accept("?") { consequent := self.ParseAssignmentExpression() self.Expect(":"); return newConditionalNode(left, consequent, self.ParseAssignmentExpression()) } return left } func (self *_parser) ParseAssignmentExpression() _node { left := self.ParseConditionlExpression() if self.matchAssignment() { switch left.Type() { case nodeIdentifier, nodeDotMember, nodeBracketMember: default: panic(self.History(-1).newSyntaxError("Invalid left-hand side in assignment")) } left = newAssignmentNode(self.Consume(), left, self.ParseAssignmentExpression()) } return left } func (self *_parser) ParseExpression() _node { left := self.ParseAssignmentExpression() if self.Match(",") { nodeList := []_node{left} for { if !self.Accept(",") { break } nodeList = append(nodeList, self.ParseAssignmentExpression()) } return newCommaNode(nodeList) } return left }