mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00

Disable new linters which aren't compatible with this code module. Upgrade github actions to fix caching issues. Run go mod to bring in new styling. Remove space on nolint declarations. Apply all changes to whitespace as required to pass goimports linter. Only trigger checks on pull_request which works for pulls from other forks, where as push only works from the same repo.
515 lines
15 KiB
Go
515 lines
15 KiB
Go
/*
|
|
Package ast declares types representing a JavaScript AST.
|
|
|
|
# Warning
|
|
|
|
The parser and AST interfaces are still works-in-progress (particularly where
|
|
node types are concerned) and may change in the future.
|
|
*/
|
|
package ast
|
|
|
|
import (
|
|
"github.com/robertkrimen/otto/file"
|
|
"github.com/robertkrimen/otto/token"
|
|
)
|
|
|
|
// All nodes implement the Node interface.
|
|
type Node interface {
|
|
Idx0() file.Idx // The index of the first character belonging to the node
|
|
Idx1() file.Idx // The index of the first character immediately after the node
|
|
}
|
|
|
|
// ========== //
|
|
// Expression //
|
|
// ========== //
|
|
|
|
type (
|
|
// All expression nodes implement the Expression interface.
|
|
Expression interface {
|
|
Node
|
|
_expressionNode()
|
|
}
|
|
|
|
ArrayLiteral struct {
|
|
LeftBracket file.Idx
|
|
RightBracket file.Idx
|
|
Value []Expression
|
|
}
|
|
|
|
AssignExpression struct {
|
|
Operator token.Token
|
|
Left Expression
|
|
Right Expression
|
|
}
|
|
|
|
BadExpression struct {
|
|
From file.Idx
|
|
To file.Idx
|
|
}
|
|
|
|
BinaryExpression struct {
|
|
Operator token.Token
|
|
Left Expression
|
|
Right Expression
|
|
Comparison bool
|
|
}
|
|
|
|
BooleanLiteral struct {
|
|
Idx file.Idx
|
|
Literal string
|
|
Value bool
|
|
}
|
|
|
|
BracketExpression struct {
|
|
Left Expression
|
|
Member Expression
|
|
LeftBracket file.Idx
|
|
RightBracket file.Idx
|
|
}
|
|
|
|
CallExpression struct {
|
|
Callee Expression
|
|
LeftParenthesis file.Idx
|
|
ArgumentList []Expression
|
|
RightParenthesis file.Idx
|
|
}
|
|
|
|
ConditionalExpression struct {
|
|
Test Expression
|
|
Consequent Expression
|
|
Alternate Expression
|
|
}
|
|
|
|
DotExpression struct {
|
|
Left Expression
|
|
Identifier *Identifier
|
|
}
|
|
|
|
EmptyExpression struct {
|
|
Begin file.Idx
|
|
End file.Idx
|
|
}
|
|
|
|
FunctionLiteral struct {
|
|
Function file.Idx
|
|
Name *Identifier
|
|
ParameterList *ParameterList
|
|
Body Statement
|
|
Source string
|
|
|
|
DeclarationList []Declaration
|
|
}
|
|
|
|
Identifier struct {
|
|
Name string
|
|
Idx file.Idx
|
|
}
|
|
|
|
NewExpression struct {
|
|
New file.Idx
|
|
Callee Expression
|
|
LeftParenthesis file.Idx
|
|
ArgumentList []Expression
|
|
RightParenthesis file.Idx
|
|
}
|
|
|
|
NullLiteral struct {
|
|
Idx file.Idx
|
|
Literal string
|
|
}
|
|
|
|
NumberLiteral struct {
|
|
Idx file.Idx
|
|
Literal string
|
|
Value interface{}
|
|
}
|
|
|
|
ObjectLiteral struct {
|
|
LeftBrace file.Idx
|
|
RightBrace file.Idx
|
|
Value []Property
|
|
}
|
|
|
|
ParameterList struct {
|
|
Opening file.Idx
|
|
List []*Identifier
|
|
Closing file.Idx
|
|
}
|
|
|
|
Property struct {
|
|
Key string
|
|
Kind string
|
|
Value Expression
|
|
}
|
|
|
|
RegExpLiteral struct {
|
|
Idx file.Idx
|
|
Literal string
|
|
Pattern string
|
|
Flags string
|
|
Value string
|
|
}
|
|
|
|
SequenceExpression struct {
|
|
Sequence []Expression
|
|
}
|
|
|
|
StringLiteral struct {
|
|
Idx file.Idx
|
|
Literal string
|
|
Value string
|
|
}
|
|
|
|
ThisExpression struct {
|
|
Idx file.Idx
|
|
}
|
|
|
|
UnaryExpression struct {
|
|
Operator token.Token
|
|
Idx file.Idx // If a prefix operation
|
|
Operand Expression
|
|
Postfix bool
|
|
}
|
|
|
|
VariableExpression struct {
|
|
Name string
|
|
Idx file.Idx
|
|
Initializer Expression
|
|
}
|
|
)
|
|
|
|
// _expressionNode
|
|
|
|
func (*ArrayLiteral) _expressionNode() {}
|
|
func (*AssignExpression) _expressionNode() {}
|
|
func (*BadExpression) _expressionNode() {}
|
|
func (*BinaryExpression) _expressionNode() {}
|
|
func (*BooleanLiteral) _expressionNode() {}
|
|
func (*BracketExpression) _expressionNode() {}
|
|
func (*CallExpression) _expressionNode() {}
|
|
func (*ConditionalExpression) _expressionNode() {}
|
|
func (*DotExpression) _expressionNode() {}
|
|
func (*EmptyExpression) _expressionNode() {}
|
|
func (*FunctionLiteral) _expressionNode() {}
|
|
func (*Identifier) _expressionNode() {}
|
|
func (*NewExpression) _expressionNode() {}
|
|
func (*NullLiteral) _expressionNode() {}
|
|
func (*NumberLiteral) _expressionNode() {}
|
|
func (*ObjectLiteral) _expressionNode() {}
|
|
func (*RegExpLiteral) _expressionNode() {}
|
|
func (*SequenceExpression) _expressionNode() {}
|
|
func (*StringLiteral) _expressionNode() {}
|
|
func (*ThisExpression) _expressionNode() {}
|
|
func (*UnaryExpression) _expressionNode() {}
|
|
func (*VariableExpression) _expressionNode() {}
|
|
|
|
// ========= //
|
|
// Statement //
|
|
// ========= //
|
|
|
|
type (
|
|
// All statement nodes implement the Statement interface.
|
|
Statement interface {
|
|
Node
|
|
_statementNode()
|
|
}
|
|
|
|
BadStatement struct {
|
|
From file.Idx
|
|
To file.Idx
|
|
}
|
|
|
|
BlockStatement struct {
|
|
LeftBrace file.Idx
|
|
List []Statement
|
|
RightBrace file.Idx
|
|
}
|
|
|
|
BranchStatement struct {
|
|
Idx file.Idx
|
|
Token token.Token
|
|
Label *Identifier
|
|
}
|
|
|
|
CaseStatement struct {
|
|
Case file.Idx
|
|
Test Expression
|
|
Consequent []Statement
|
|
}
|
|
|
|
CatchStatement struct {
|
|
Catch file.Idx
|
|
Parameter *Identifier
|
|
Body Statement
|
|
}
|
|
|
|
DebuggerStatement struct {
|
|
Debugger file.Idx
|
|
}
|
|
|
|
DoWhileStatement struct {
|
|
Do file.Idx
|
|
Test Expression
|
|
Body Statement
|
|
}
|
|
|
|
EmptyStatement struct {
|
|
Semicolon file.Idx
|
|
}
|
|
|
|
ExpressionStatement struct {
|
|
Expression Expression
|
|
}
|
|
|
|
ForInStatement struct {
|
|
For file.Idx
|
|
Into Expression
|
|
Source Expression
|
|
Body Statement
|
|
}
|
|
|
|
ForStatement struct {
|
|
For file.Idx
|
|
Initializer Expression
|
|
Update Expression
|
|
Test Expression
|
|
Body Statement
|
|
}
|
|
|
|
FunctionStatement struct {
|
|
Function *FunctionLiteral
|
|
}
|
|
|
|
IfStatement struct {
|
|
If file.Idx
|
|
Test Expression
|
|
Consequent Statement
|
|
Alternate Statement
|
|
}
|
|
|
|
LabelledStatement struct {
|
|
Label *Identifier
|
|
Colon file.Idx
|
|
Statement Statement
|
|
}
|
|
|
|
ReturnStatement struct {
|
|
Return file.Idx
|
|
Argument Expression
|
|
}
|
|
|
|
SwitchStatement struct {
|
|
Switch file.Idx
|
|
Discriminant Expression
|
|
Default int
|
|
Body []*CaseStatement
|
|
}
|
|
|
|
ThrowStatement struct {
|
|
Throw file.Idx
|
|
Argument Expression
|
|
}
|
|
|
|
TryStatement struct {
|
|
Try file.Idx
|
|
Body Statement
|
|
Catch *CatchStatement
|
|
Finally Statement
|
|
}
|
|
|
|
VariableStatement struct {
|
|
Var file.Idx
|
|
List []Expression
|
|
}
|
|
|
|
WhileStatement struct {
|
|
While file.Idx
|
|
Test Expression
|
|
Body Statement
|
|
}
|
|
|
|
WithStatement struct {
|
|
With file.Idx
|
|
Object Expression
|
|
Body Statement
|
|
}
|
|
)
|
|
|
|
// _statementNode
|
|
|
|
func (*BadStatement) _statementNode() {}
|
|
func (*BlockStatement) _statementNode() {}
|
|
func (*BranchStatement) _statementNode() {}
|
|
func (*CaseStatement) _statementNode() {}
|
|
func (*CatchStatement) _statementNode() {}
|
|
func (*DebuggerStatement) _statementNode() {}
|
|
func (*DoWhileStatement) _statementNode() {}
|
|
func (*EmptyStatement) _statementNode() {}
|
|
func (*ExpressionStatement) _statementNode() {}
|
|
func (*ForInStatement) _statementNode() {}
|
|
func (*ForStatement) _statementNode() {}
|
|
func (*FunctionStatement) _statementNode() {}
|
|
func (*IfStatement) _statementNode() {}
|
|
func (*LabelledStatement) _statementNode() {}
|
|
func (*ReturnStatement) _statementNode() {}
|
|
func (*SwitchStatement) _statementNode() {}
|
|
func (*ThrowStatement) _statementNode() {}
|
|
func (*TryStatement) _statementNode() {}
|
|
func (*VariableStatement) _statementNode() {}
|
|
func (*WhileStatement) _statementNode() {}
|
|
func (*WithStatement) _statementNode() {}
|
|
|
|
// =========== //
|
|
// Declaration //
|
|
// =========== //
|
|
|
|
type (
|
|
// All declaration nodes implement the Declaration interface.
|
|
Declaration interface {
|
|
_declarationNode()
|
|
}
|
|
|
|
FunctionDeclaration struct {
|
|
Function *FunctionLiteral
|
|
}
|
|
|
|
VariableDeclaration struct {
|
|
Var file.Idx
|
|
List []*VariableExpression
|
|
}
|
|
)
|
|
|
|
// _declarationNode
|
|
|
|
func (*FunctionDeclaration) _declarationNode() {}
|
|
func (*VariableDeclaration) _declarationNode() {}
|
|
|
|
// ==== //
|
|
// Node //
|
|
// ==== //
|
|
|
|
type Program struct {
|
|
Body []Statement
|
|
|
|
DeclarationList []Declaration
|
|
|
|
File *file.File
|
|
|
|
Comments CommentMap
|
|
}
|
|
|
|
// ==== //
|
|
// Idx0 //
|
|
// ==== //
|
|
|
|
func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket }
|
|
func (self *AssignExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
|
func (self *BadExpression) Idx0() file.Idx { return self.From }
|
|
func (self *BinaryExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
|
func (self *BooleanLiteral) Idx0() file.Idx { return self.Idx }
|
|
func (self *BracketExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
|
func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() }
|
|
func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() }
|
|
func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
|
func (self *EmptyExpression) Idx0() file.Idx { return self.Begin }
|
|
func (self *FunctionLiteral) Idx0() file.Idx { return self.Function }
|
|
func (self *Identifier) Idx0() file.Idx { return self.Idx }
|
|
func (self *NewExpression) Idx0() file.Idx { return self.New }
|
|
func (self *NullLiteral) Idx0() file.Idx { return self.Idx }
|
|
func (self *NumberLiteral) Idx0() file.Idx { return self.Idx }
|
|
func (self *ObjectLiteral) Idx0() file.Idx { return self.LeftBrace }
|
|
func (self *RegExpLiteral) Idx0() file.Idx { return self.Idx }
|
|
func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx0() }
|
|
func (self *StringLiteral) Idx0() file.Idx { return self.Idx }
|
|
func (self *ThisExpression) Idx0() file.Idx { return self.Idx }
|
|
func (self *UnaryExpression) Idx0() file.Idx { return self.Idx }
|
|
func (self *VariableExpression) Idx0() file.Idx { return self.Idx }
|
|
|
|
func (self *BadStatement) Idx0() file.Idx { return self.From }
|
|
func (self *BlockStatement) Idx0() file.Idx { return self.LeftBrace }
|
|
func (self *BranchStatement) Idx0() file.Idx { return self.Idx }
|
|
func (self *CaseStatement) Idx0() file.Idx { return self.Case }
|
|
func (self *CatchStatement) Idx0() file.Idx { return self.Catch }
|
|
func (self *DebuggerStatement) Idx0() file.Idx { return self.Debugger }
|
|
func (self *DoWhileStatement) Idx0() file.Idx { return self.Do }
|
|
func (self *EmptyStatement) Idx0() file.Idx { return self.Semicolon }
|
|
func (self *ExpressionStatement) Idx0() file.Idx { return self.Expression.Idx0() }
|
|
func (self *ForInStatement) Idx0() file.Idx { return self.For }
|
|
func (self *ForStatement) Idx0() file.Idx { return self.For }
|
|
func (self *FunctionStatement) Idx0() file.Idx { return self.Function.Idx0() }
|
|
func (self *IfStatement) Idx0() file.Idx { return self.If }
|
|
func (self *LabelledStatement) Idx0() file.Idx { return self.Label.Idx0() }
|
|
func (self *Program) Idx0() file.Idx { return self.Body[0].Idx0() }
|
|
func (self *ReturnStatement) Idx0() file.Idx { return self.Return }
|
|
func (self *SwitchStatement) Idx0() file.Idx { return self.Switch }
|
|
func (self *ThrowStatement) Idx0() file.Idx { return self.Throw }
|
|
func (self *TryStatement) Idx0() file.Idx { return self.Try }
|
|
func (self *VariableStatement) Idx0() file.Idx { return self.Var }
|
|
func (self *WhileStatement) Idx0() file.Idx { return self.While }
|
|
func (self *WithStatement) Idx0() file.Idx { return self.With }
|
|
|
|
// ==== //
|
|
// Idx1 //
|
|
// ==== //
|
|
|
|
func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket }
|
|
func (self *AssignExpression) Idx1() file.Idx { return self.Right.Idx1() }
|
|
func (self *BadExpression) Idx1() file.Idx { return self.To }
|
|
func (self *BinaryExpression) Idx1() file.Idx { return self.Right.Idx1() }
|
|
func (self *BooleanLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
|
func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket + 1 }
|
|
func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 }
|
|
func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() }
|
|
func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() }
|
|
func (self *EmptyExpression) Idx1() file.Idx { return self.End }
|
|
func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
|
|
func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) }
|
|
func (self *NewExpression) Idx1() file.Idx { return self.RightParenthesis + 1 }
|
|
func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null"
|
|
func (self *NumberLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
|
func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace }
|
|
func (self *RegExpLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
|
func (self *SequenceExpression) Idx1() file.Idx { return self.Sequence[0].Idx1() }
|
|
func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
|
func (self *ThisExpression) Idx1() file.Idx { return self.Idx + 4 }
|
|
func (self *UnaryExpression) Idx1() file.Idx {
|
|
if self.Postfix {
|
|
return self.Operand.Idx1() + 2 // ++ --
|
|
}
|
|
return self.Operand.Idx1()
|
|
}
|
|
func (self *VariableExpression) Idx1() file.Idx {
|
|
if self.Initializer == nil {
|
|
return file.Idx(int(self.Idx) + len(self.Name) + 1)
|
|
}
|
|
return self.Initializer.Idx1()
|
|
}
|
|
|
|
func (self *BadStatement) Idx1() file.Idx { return self.To }
|
|
func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 }
|
|
func (self *BranchStatement) Idx1() file.Idx { return self.Idx }
|
|
func (self *CaseStatement) Idx1() file.Idx { return self.Consequent[len(self.Consequent)-1].Idx1() }
|
|
func (self *CatchStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
|
func (self *DebuggerStatement) Idx1() file.Idx { return self.Debugger + 8 }
|
|
func (self *DoWhileStatement) Idx1() file.Idx { return self.Test.Idx1() }
|
|
func (self *EmptyStatement) Idx1() file.Idx { return self.Semicolon + 1 }
|
|
func (self *ExpressionStatement) Idx1() file.Idx { return self.Expression.Idx1() }
|
|
func (self *ForInStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
|
func (self *ForStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
|
func (self *FunctionStatement) Idx1() file.Idx { return self.Function.Idx1() }
|
|
func (self *IfStatement) Idx1() file.Idx {
|
|
if self.Alternate != nil {
|
|
return self.Alternate.Idx1()
|
|
}
|
|
return self.Consequent.Idx1()
|
|
}
|
|
func (self *LabelledStatement) Idx1() file.Idx { return self.Colon + 1 }
|
|
func (self *Program) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() }
|
|
func (self *ReturnStatement) Idx1() file.Idx { return self.Return }
|
|
func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() }
|
|
func (self *ThrowStatement) Idx1() file.Idx { return self.Throw }
|
|
func (self *TryStatement) Idx1() file.Idx { return self.Try }
|
|
func (self *VariableStatement) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }
|
|
func (self *WhileStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
|
func (self *WithStatement) Idx1() file.Idx { return self.Body.Idx1() }
|