mirror of
https://github.com/robertkrimen/otto
synced 2025-09-28 18:45:22 +08:00
Line tracking for error reporting
This commit is contained in:
parent
f81f540a01
commit
326264ae3e
1
Makefile
1
Makefile
|
@ -18,6 +18,7 @@ TEST := -v --run _eval
|
|||
TEST := -v --run Broken
|
||||
TEST := -v --run ParseSuccess
|
||||
TEST := .
|
||||
TEST := -v --run OttoError
|
||||
|
||||
test:
|
||||
go test $(TEST)
|
||||
|
|
9
error.go
9
error.go
|
@ -8,6 +8,8 @@ import (
|
|||
type _error struct {
|
||||
Name string
|
||||
Message string
|
||||
|
||||
Line int // Hackish -- line where the error/exception occurred
|
||||
}
|
||||
|
||||
var messageDetail map[string]string = map[string]string{
|
||||
|
@ -48,6 +50,7 @@ func newError(name string, argumentList... interface{}) _error {
|
|||
return _error{
|
||||
Name: name,
|
||||
Message: messageFromDescription(description, argumentList...),
|
||||
Line: -1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +89,11 @@ func catchPanic(function func()) (err error) {
|
|||
err = errors.New(caught.String())
|
||||
return
|
||||
case _error:
|
||||
err = errors.New(caught.String())
|
||||
if caught.Line == -1 {
|
||||
err = errors.New(caught.String())
|
||||
} else {
|
||||
err = errors.New(fmt.Sprintf("%s (line %d)", caught.String(), caught.Line))
|
||||
}
|
||||
return
|
||||
case _result:
|
||||
if caught.Kind == resultThrow {
|
||||
|
|
15
evaluate.go
15
evaluate.go
|
@ -20,6 +20,21 @@ func (self *_runtime) evaluateBody(list []_node) Value {
|
|||
}
|
||||
|
||||
func (self *_runtime) evaluate(node _node) Value {
|
||||
defer func() {
|
||||
// This defer is lame (unecessary overhead)
|
||||
// It would be better to mark the errors at the source
|
||||
if caught := recover(); caught != nil {
|
||||
switch caught := caught.(type) {
|
||||
case _error:
|
||||
if caught.Line == -1 {
|
||||
caught.Line = node.position()
|
||||
}
|
||||
panic(caught) // Panic the modified _error
|
||||
}
|
||||
panic(caught)
|
||||
}
|
||||
}()
|
||||
|
||||
switch node := node.(type) {
|
||||
|
||||
case *_variableDeclarationListNode:
|
||||
|
|
15
node.go
15
node.go
|
@ -10,6 +10,8 @@ import (
|
|||
type _node interface {
|
||||
Type() _nodeType
|
||||
String() string
|
||||
setPosition(int)
|
||||
position() int
|
||||
}
|
||||
|
||||
type _nodeType int
|
||||
|
@ -18,6 +20,19 @@ func (self _nodeType) Type() _nodeType {
|
|||
return self
|
||||
}
|
||||
|
||||
type _node_ struct {
|
||||
_nodeType
|
||||
Line int // Line in the source
|
||||
}
|
||||
|
||||
func (self *_node_) setPosition(Line int) {
|
||||
self.Line = Line
|
||||
}
|
||||
|
||||
func (self *_node_) position() int {
|
||||
return self.Line
|
||||
}
|
||||
|
||||
const (
|
||||
nodeEmpty _nodeType = iota
|
||||
nodeCall
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
type _arrayNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
nodeList []_node
|
||||
}
|
||||
|
||||
|
@ -26,6 +27,7 @@ func (self *_arrayNode) String() string {
|
|||
|
||||
type _assignmentNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Assignment string
|
||||
Operator string
|
||||
Left _node
|
||||
|
@ -48,6 +50,7 @@ func (self _assignmentNode) String() string {
|
|||
|
||||
type _binaryOperationNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Operator string
|
||||
Left _node
|
||||
Right _node
|
||||
|
@ -68,6 +71,7 @@ func (self _binaryOperationNode) String() string {
|
|||
|
||||
type _callNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Callee _node
|
||||
ArgumentList []_node
|
||||
}
|
||||
|
@ -86,6 +90,7 @@ func (self _callNode) String() string {
|
|||
|
||||
type _commaNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Sequence []_node
|
||||
}
|
||||
|
||||
|
@ -102,6 +107,7 @@ func (self _commaNode) String() string {
|
|||
|
||||
type _comparisonNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Comparator string
|
||||
Left _node
|
||||
Right _node
|
||||
|
@ -122,6 +128,7 @@ func (self _comparisonNode) String() string {
|
|||
|
||||
type _conditionalNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Test _node
|
||||
Consequent _node
|
||||
Alternate _node
|
||||
|
@ -141,6 +148,7 @@ func (self _conditionalNode) String() string {
|
|||
|
||||
type _functionNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
_declaration bool
|
||||
ParameterList []string
|
||||
Body []_node
|
||||
|
@ -165,6 +173,7 @@ func (self *_functionNode) AddParameter(identifier string) {
|
|||
|
||||
type _identifierNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Value string
|
||||
}
|
||||
|
||||
|
@ -181,6 +190,7 @@ func (self *_identifierNode) String() string {
|
|||
|
||||
type _dotMemberNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Target _node
|
||||
Member string
|
||||
}
|
||||
|
@ -199,6 +209,7 @@ func (self *_dotMemberNode) String() string {
|
|||
|
||||
type _bracketMemberNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Target _node
|
||||
Member _node
|
||||
}
|
||||
|
@ -217,6 +228,7 @@ func (self *_bracketMemberNode) String() string {
|
|||
|
||||
type _newNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Callee _node
|
||||
ArgumentList []_node
|
||||
}
|
||||
|
@ -235,6 +247,7 @@ func (self _newNode) String() string {
|
|||
|
||||
type _objectNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
propertyList []*_objectPropertyNode
|
||||
}
|
||||
|
||||
|
@ -257,6 +270,7 @@ func (self *_objectNode) String() string {
|
|||
|
||||
type _objectPropertyNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Key string
|
||||
Value _node
|
||||
}
|
||||
|
@ -275,6 +289,7 @@ func (self *_objectPropertyNode) String() string {
|
|||
|
||||
type _regExpNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Pattern string
|
||||
Flags string
|
||||
}
|
||||
|
@ -293,6 +308,7 @@ func (self *_regExpNode) String() string {
|
|||
|
||||
type _thisNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
}
|
||||
|
||||
func newThisNode() *_thisNode {
|
||||
|
@ -307,6 +323,7 @@ func (self *_thisNode) String() string {
|
|||
|
||||
type _unaryOperationNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Operator string
|
||||
Target _node
|
||||
}
|
||||
|
@ -334,6 +351,7 @@ const (
|
|||
|
||||
type _valueNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Value Value
|
||||
Text string
|
||||
Kind _valueNodeType
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
type _blockNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Body []_node
|
||||
}
|
||||
|
||||
|
@ -24,6 +25,7 @@ func (self _blockNode) String() string {
|
|||
|
||||
type _breakNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Target string
|
||||
}
|
||||
|
||||
|
@ -40,6 +42,7 @@ func (self _breakNode) String() string {
|
|||
|
||||
type _continueNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Target string
|
||||
}
|
||||
|
||||
|
@ -56,6 +59,7 @@ func (self _continueNode) String() string {
|
|||
|
||||
type _doWhileNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Test _node
|
||||
Body _node
|
||||
_labelSet _labelSet
|
||||
|
@ -77,6 +81,7 @@ func (self _doWhileNode) String() string {
|
|||
|
||||
type _emptyNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
}
|
||||
|
||||
func newEmptyNode() *_emptyNode {
|
||||
|
@ -91,6 +96,7 @@ func (self _emptyNode) String() string {
|
|||
|
||||
type _forNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Initial _node
|
||||
Test _node
|
||||
Update _node
|
||||
|
@ -122,6 +128,7 @@ func (self _forNode) String() string {
|
|||
|
||||
type _forInNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Into _node
|
||||
Source _node
|
||||
Body _node
|
||||
|
@ -150,6 +157,7 @@ func (self _forInNode) String() string {
|
|||
|
||||
type _ifNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Test _node
|
||||
Consequent _node
|
||||
Alternate _node
|
||||
|
@ -180,6 +188,7 @@ func (self _ifNode) String() string {
|
|||
|
||||
type _programNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Body []_node
|
||||
VariableList []_declaration
|
||||
FunctionList []_declaration
|
||||
|
@ -206,6 +215,7 @@ func (self _programNode) toFunction(parameterList []string) *_functionNode {
|
|||
|
||||
type _returnNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Argument _node
|
||||
}
|
||||
|
||||
|
@ -224,6 +234,7 @@ func (self _returnNode) String() string {
|
|||
|
||||
type _switchNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Discriminant _node
|
||||
Default int
|
||||
CaseList [](*_caseNode)
|
||||
|
@ -247,6 +258,7 @@ func (self _switchNode) String() string {
|
|||
|
||||
type _caseNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Test _node
|
||||
Body []_node
|
||||
}
|
||||
|
@ -272,6 +284,7 @@ func (self _caseNode) String() string {
|
|||
|
||||
type _throwNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Argument _node
|
||||
}
|
||||
|
||||
|
@ -288,6 +301,7 @@ func (self _throwNode) String() string {
|
|||
|
||||
type _tryCatchNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Try _node
|
||||
Catch *_catchNode
|
||||
Finally *_blockNode
|
||||
|
@ -320,6 +334,7 @@ func (self *_tryCatchNode) AddCatch(identifier string, body *_blockNode) {
|
|||
|
||||
type _catchNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Identifier string
|
||||
Body *_blockNode
|
||||
}
|
||||
|
@ -338,6 +353,7 @@ func (self _catchNode) String() string {
|
|||
|
||||
type _variableDeclarationListNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
VariableList []*_variableDeclarationNode
|
||||
}
|
||||
|
||||
|
@ -353,6 +369,7 @@ func (self _variableDeclarationListNode) String() string {
|
|||
|
||||
type _variableDeclarationNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Identifier string
|
||||
Operator string
|
||||
Initializer _node
|
||||
|
@ -374,6 +391,7 @@ func (self _variableDeclarationNode) String() string {
|
|||
|
||||
type _whileNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Test _node
|
||||
Body _node
|
||||
_labelSet _labelSet
|
||||
|
@ -395,6 +413,7 @@ func (self _whileNode) String() string {
|
|||
|
||||
type _withNode struct {
|
||||
_nodeType
|
||||
_node_
|
||||
Object _node
|
||||
Body _node
|
||||
}
|
||||
|
|
|
@ -21,4 +21,12 @@ func TestOttoError(t *testing.T) {
|
|||
|
||||
_, err = ToValue([]byte{})
|
||||
Is(err, "TypeError: Unable to convert value: [] ([]uint8)")
|
||||
|
||||
_, err = Otto.Run(`
|
||||
(function(){
|
||||
return abcdef.length
|
||||
})()
|
||||
`)
|
||||
Is(err, "ReferenceError: abcdef is not defined (line 2)")
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ func (self *_parser) ParsePrimaryExpression() _node {
|
|||
return self.ParseFunction(false)
|
||||
case "this":
|
||||
self.Next()
|
||||
return newThisNode()
|
||||
node := newThisNode()
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "{":
|
||||
return self.ParseObjectLiteral()
|
||||
case "[":
|
||||
|
@ -56,7 +58,9 @@ func (self *_parser) ParseObjectProperty() *_objectPropertyNode {
|
|||
self.Expect(":")
|
||||
value := self.ParseAssignmentExpression()
|
||||
|
||||
return newObjectPropertyNode(key, value)
|
||||
node := newObjectPropertyNode(key, value)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
func (self *_parser) ParseRegExpLiteral(token _token) *_regExpNode {
|
||||
|
@ -74,12 +78,15 @@ func (self *_parser) ParseRegExpLiteral(token _token) *_regExpNode {
|
|||
panic(token.newSyntaxError("Invalid regular expression"))
|
||||
}
|
||||
|
||||
return newRegExpNode(pattern_, flags)
|
||||
node := newRegExpNode(pattern_, flags)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
func (self *_parser) ParseObjectLiteral() *_objectNode {
|
||||
|
||||
node := newObjectNode()
|
||||
self.markNode(node)
|
||||
|
||||
self.Expect("{")
|
||||
for !self.Match("}") {
|
||||
|
@ -111,7 +118,9 @@ func (self *_parser) ParseArrayLiteral() *_arrayNode {
|
|||
}
|
||||
self.Expect("]")
|
||||
|
||||
return newArrayNode(nodeList)
|
||||
node := newArrayNode(nodeList)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
func (self *_parser) ParseArgumentList() (argumentList []_node) {
|
||||
|
@ -131,6 +140,7 @@ func (self *_parser) ParseArgumentList() (argumentList []_node) {
|
|||
|
||||
func (self *_parser) ParseCallExpression(left _node) _node {
|
||||
left = newCallNode(left)
|
||||
self.markNode(left)
|
||||
left.(*_callNode).ArgumentList = self.ParseArgumentList()
|
||||
return left
|
||||
}
|
||||
|
@ -138,19 +148,24 @@ func (self *_parser) ParseCallExpression(left _node) _node {
|
|||
func (self *_parser) ParseDotMember(left _node) _node {
|
||||
self.Expect(".")
|
||||
member := self.ConsumeIdentifier().Value
|
||||
return newDotMemberNode(left, member)
|
||||
node := newDotMemberNode(left, member)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
func (self *_parser) ParseBracketMember(left _node) _node {
|
||||
self.Expect("[")
|
||||
member := self.ParseExpression()
|
||||
self.Expect("]")
|
||||
return newBracketMemberNode(left, member)
|
||||
node := newBracketMemberNode(left, member)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
func (self *_parser) ParseNewExpression() _node {
|
||||
self.Expect("new")
|
||||
node := newnewNode(self.ParseLeftHandSideExpression())
|
||||
self.markNode(node)
|
||||
if self.Match("(") {
|
||||
node.ArgumentList = self.ParseArgumentList()
|
||||
}
|
||||
|
@ -219,7 +234,9 @@ func (self *_parser) ParsePostfixExpression() _node {
|
|||
default:
|
||||
panic(self.History(-1).newSyntaxError("Invalid left-hand side in assignment"))
|
||||
}
|
||||
return newUnaryOperationNode("=" + self.Consume(), left)
|
||||
node := newUnaryOperationNode("=" + self.Consume(), left)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -232,7 +249,9 @@ func (self *_parser) ParseUnaryExpression() _node {
|
|||
|
||||
switch token := self.Peek(); token.Kind {
|
||||
case "+", "-", "!", "~":
|
||||
return newUnaryOperationNode(self.Consume(), self.ParseUnaryExpression())
|
||||
node := newUnaryOperationNode(self.Consume(), self.ParseUnaryExpression())
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "++", "--": // Prefix, either ++= or --=
|
||||
operation := self.Consume()
|
||||
left := self.ParseUnaryExpression()
|
||||
|
@ -241,9 +260,13 @@ func (self *_parser) ParseUnaryExpression() _node {
|
|||
default:
|
||||
panic(self.History(-1).newSyntaxError("Invalid left-hand side in assignment"))
|
||||
}
|
||||
return newUnaryOperationNode(operation + "=", left)
|
||||
node := newUnaryOperationNode(operation + "=", left)
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "delete", "void", "typeof":
|
||||
return newUnaryOperationNode(self.Consume(), self.ParseUnaryExpression())
|
||||
node := newUnaryOperationNode(self.Consume(), self.ParseUnaryExpression())
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
return self.ParsePostfixExpression()
|
||||
|
@ -256,6 +279,7 @@ REPEAT:
|
|||
switch self.Peek().Kind {
|
||||
case "*", "/", "%":
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseUnaryExpression())
|
||||
self.markNode(left)
|
||||
goto REPEAT
|
||||
}
|
||||
|
||||
|
@ -269,6 +293,7 @@ REPEAT:
|
|||
switch self.Peek().Kind {
|
||||
case "+", "-":
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseMultiplicativeExpression())
|
||||
self.markNode(left)
|
||||
goto REPEAT
|
||||
}
|
||||
|
||||
|
@ -282,6 +307,7 @@ REPEAT:
|
|||
switch self.Peek().Kind {
|
||||
case "<<", ">>", ">>>":
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseAdditiveExpression())
|
||||
self.markNode(left)
|
||||
goto REPEAT
|
||||
}
|
||||
return left
|
||||
|
@ -295,14 +321,20 @@ func (self *_parser) ParseRelationalExpression() _node {
|
|||
|
||||
switch self.Peek().Kind {
|
||||
case "<", ">", "<=", ">=":
|
||||
return newComparisonNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
node := newComparisonNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "instanceof":
|
||||
return newBinaryOperationNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
node := newBinaryOperationNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "in":
|
||||
if !self.Scope().AllowIn {
|
||||
return left
|
||||
}
|
||||
return newBinaryOperationNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
node := newBinaryOperationNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
self.markNode(node)
|
||||
return node
|
||||
|
||||
}
|
||||
|
||||
|
@ -316,6 +348,7 @@ REPEAT:
|
|||
switch self.Peek().Kind {
|
||||
case "==", "!=", "===", "!==":
|
||||
left = newComparisonNode(self.Consume(), left, self.ParseRelationalExpression())
|
||||
self.markNode(left)
|
||||
goto REPEAT
|
||||
}
|
||||
|
||||
|
@ -327,6 +360,7 @@ func (self *_parser) ParseBitwiseANDExpression() _node {
|
|||
|
||||
for self.Match("&") {
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseEqualityExpression())
|
||||
self.markNode(left)
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -337,6 +371,7 @@ func (self *_parser) ParseBitwiseXORExpression() _node {
|
|||
|
||||
for self.Match("^") {
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseBitwiseANDExpression())
|
||||
self.markNode(left)
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -347,6 +382,7 @@ func (self *_parser) ParseBitwiseORExpression() _node {
|
|||
|
||||
for self.Match("|") {
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseBitwiseXORExpression())
|
||||
self.markNode(left)
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -357,6 +393,7 @@ func (self *_parser) ParseLogicalANDExpression() _node {
|
|||
|
||||
for self.Match("&&") {
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseBitwiseORExpression())
|
||||
self.markNode(left)
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -367,6 +404,7 @@ func (self *_parser) ParseLogicalORExpression() _node {
|
|||
|
||||
for self.Match("||") {
|
||||
left = newBinaryOperationNode(self.Consume(), left, self.ParseLogicalANDExpression())
|
||||
self.markNode(left)
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -378,7 +416,9 @@ func (self *_parser) ParseConditionlExpression() _node {
|
|||
if self.Accept("?") {
|
||||
consequent := self.ParseAssignmentExpression()
|
||||
self.Expect(":");
|
||||
return newConditionalNode(left, consequent, self.ParseAssignmentExpression())
|
||||
node := newConditionalNode(left, consequent, self.ParseAssignmentExpression())
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
return left
|
||||
|
@ -393,6 +433,7 @@ func (self *_parser) ParseAssignmentExpression() _node {
|
|||
panic(self.History(-1).newSyntaxError("Invalid left-hand side in assignment"))
|
||||
}
|
||||
left = newAssignmentNode(self.Consume(), left, self.ParseAssignmentExpression())
|
||||
self.markNode(left)
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
@ -408,7 +449,9 @@ func (self *_parser) ParseExpression() _node {
|
|||
}
|
||||
nodeList = append(nodeList, self.ParseAssignmentExpression())
|
||||
}
|
||||
return newCommaNode(nodeList)
|
||||
node := newCommaNode(nodeList)
|
||||
self.markNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
return left
|
||||
|
|
|
@ -8,7 +8,9 @@ func (self *_parser) ParseStatement() _node {
|
|||
switch self.Peek().Kind {
|
||||
case ";":
|
||||
self.Next()
|
||||
return newEmptyNode()
|
||||
node := newEmptyNode()
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "if":
|
||||
return self.ParseIf()
|
||||
case "do":
|
||||
|
@ -30,7 +32,9 @@ func (self *_parser) ParseStatement() _node {
|
|||
case "function":
|
||||
self.ParseFunctionDeclaration()
|
||||
// TODO Should be FunctionDeclarationStatement
|
||||
return newEmptyNode()
|
||||
node := newEmptyNode()
|
||||
self.markNode(node)
|
||||
return node
|
||||
case "switch":
|
||||
return self.ParseSwitch()
|
||||
case "return":
|
||||
|
@ -234,6 +238,7 @@ func (self *_parser) parseStatementUntil(stop func() bool) []_node {
|
|||
|
||||
func (self *_parser) ParseBlock() *_blockNode {
|
||||
node := newBlockNode()
|
||||
self.markNode(node)
|
||||
|
||||
self.Expect("{")
|
||||
node.Body = self.parseStatementUntil(func() bool {
|
||||
|
@ -250,11 +255,12 @@ func (self *_parser) ParseReturnStatement() _node {
|
|||
panic(self.History(-1).newSyntaxError("Illegal return statement"))
|
||||
}
|
||||
|
||||
if self.Match("\n") {
|
||||
return newReturnNode()
|
||||
}
|
||||
|
||||
node := newReturnNode()
|
||||
self.markNode(node)
|
||||
|
||||
if self.Match("\n") {
|
||||
return node
|
||||
}
|
||||
|
||||
if !self.Match(";") {
|
||||
if !self.Match("}") && !self.Match("EOF") {
|
||||
|
@ -276,6 +282,7 @@ func (self *_parser) ParseThrow() _node {
|
|||
}
|
||||
|
||||
node := newThrowNode(self.ParseExpression())
|
||||
self.markNode(node)
|
||||
|
||||
self.ConsumeSemicolon()
|
||||
|
||||
|
@ -289,7 +296,8 @@ func (self *_parser) ParseSwitch() _node {
|
|||
discriminant := self.ParseExpression()
|
||||
self.Expect(")")
|
||||
|
||||
_switchNode := newSwitchNode(discriminant)
|
||||
switchNode := newSwitchNode(discriminant)
|
||||
self.markNode(switchNode)
|
||||
|
||||
self.Expect("{")
|
||||
|
||||
|
@ -301,17 +309,17 @@ func (self *_parser) ParseSwitch() _node {
|
|||
|
||||
result := self.ParseCase()
|
||||
if result.Test == nil {
|
||||
if _switchNode.Default != -1 {
|
||||
if switchNode.Default != -1 {
|
||||
panic(hereBeDragons("Already saw a default:"))
|
||||
}
|
||||
_switchNode.Default = i
|
||||
switchNode.Default = i
|
||||
}
|
||||
_switchNode.AddCase(result)
|
||||
switchNode.AddCase(result)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return _switchNode
|
||||
return switchNode
|
||||
}
|
||||
|
||||
func (self *_parser) ParseCase() *_caseNode {
|
||||
|
@ -319,9 +327,11 @@ func (self *_parser) ParseCase() *_caseNode {
|
|||
var node *_caseNode
|
||||
if self.Accept("default") {
|
||||
node = newDefaultCaseNode()
|
||||
self.markNode(node)
|
||||
} else {
|
||||
self.Expect("case")
|
||||
node = newCaseNode(self.ParseExpression())
|
||||
self.markNode(node)
|
||||
}
|
||||
self.Expect(":")
|
||||
|
||||
|
@ -338,6 +348,7 @@ func (self *_parser) ParseCase() *_caseNode {
|
|||
|
||||
func (self *_parser) ParseVariable() *_variableDeclarationNode {
|
||||
node := newVariableDeclarationNode(self.ConsumeIdentifier().Value)
|
||||
self.markNode(node)
|
||||
|
||||
for _, value := range []string{"=", ":="} {
|
||||
if self.Accept(value) {
|
||||
|
@ -354,6 +365,7 @@ func (self *_parser) ParseVariableDeclaration() *_variableDeclarationListNode {
|
|||
self.Expect("var")
|
||||
|
||||
node := newVariableDeclarationListNode()
|
||||
self.markNode(node)
|
||||
|
||||
for {
|
||||
variable := self.ParseVariable()
|
||||
|
@ -381,12 +393,13 @@ func (self *_parser) ParseFunction(declare bool) _node {
|
|||
|
||||
self.Expect("function")
|
||||
|
||||
_functionNode := newFunctionNode()
|
||||
functionNode := newFunctionNode()
|
||||
self.markNode(functionNode)
|
||||
|
||||
if self.Match("identifier") {
|
||||
identifier := self.ConsumeIdentifier()
|
||||
if declare {
|
||||
self.Scope().AddFunction(identifier.Value, _functionNode)
|
||||
self.Scope().AddFunction(identifier.Value, functionNode)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,9 +411,9 @@ func (self *_parser) ParseFunction(declare bool) _node {
|
|||
self.Expect("(")
|
||||
for !self.Accept(")") {
|
||||
identifier := self.ConsumeIdentifier().Value
|
||||
_functionNode.AddParameter(identifier)
|
||||
functionNode.AddParameter(identifier)
|
||||
if identifier == "arguments" {
|
||||
_functionNode.ArgumentsIsParameter = true
|
||||
functionNode.ArgumentsIsParameter = true
|
||||
}
|
||||
if !self.Match(")") {
|
||||
self.Expect(",")
|
||||
|
@ -411,14 +424,14 @@ func (self *_parser) ParseFunction(declare bool) _node {
|
|||
self.EnterScope()
|
||||
defer self.LeaveScope()
|
||||
self.parseInFunction(func() _node {
|
||||
_functionNode.Body = self.ParseBlock().Body
|
||||
functionNode.Body = self.ParseBlock().Body
|
||||
return nil
|
||||
})
|
||||
_functionNode.VariableList = self.Scope().VariableList
|
||||
_functionNode.FunctionList = self.Scope().FunctionList
|
||||
functionNode.VariableList = self.Scope().VariableList
|
||||
functionNode.FunctionList = self.Scope().FunctionList
|
||||
}
|
||||
|
||||
return _functionNode;
|
||||
return functionNode;
|
||||
}
|
||||
|
||||
/*func (self *_parser) ParseFunctionParameterList() []string {*/
|
||||
|
@ -448,6 +461,7 @@ func (self *_parser) parseForIn(into _node) *_forInNode {
|
|||
})
|
||||
|
||||
node := newForInNode(into, source, body)
|
||||
self.markNode(node)
|
||||
node._labelSet[""] = true
|
||||
return node
|
||||
}
|
||||
|
@ -473,6 +487,7 @@ func (self *_parser) parseFor(initial _node) *_forNode {
|
|||
})
|
||||
|
||||
node := newForNode(initial, test, update, body)
|
||||
self.markNode(node)
|
||||
node._labelSet[""] = true
|
||||
return node
|
||||
}
|
||||
|
|
|
@ -280,3 +280,8 @@ func (self *_parser) Unexpected(token _token) *_syntaxError {
|
|||
}
|
||||
return token.newSyntaxError("Unexpected token %s", token.Text)
|
||||
}
|
||||
|
||||
func (self *_parser) markNode(node _node) {
|
||||
node.setPosition(self.lexer.Line)
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestSynopsis(t *testing.T) {
|
|||
|
||||
{
|
||||
value, err := Otto.Run("abcdefghijlmnopqrstuvwxyz.length")
|
||||
Is(err, "ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined")
|
||||
Is(err, "ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined (line 0)")
|
||||
if err != nil {
|
||||
IsTrue(value.IsUndefined())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user