1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-19 19:55:30 +08:00
otto/ast/node.go
Tomoki Yamaguchi 589611c3ae
fix: positions of expressions (#505)
Fix Idx1 of ConditionalExpression so that it points to the next character after alternate expression.
Fix Idx1 of SequenceExpression to return Idx1 of the last sequence element, not first.
Fix Idx0 of unary expression to point to the start of operand in case of a postfix operator.
Fix Idx1 of VariableExpression so that it points to the character right after the name literal if the
expression does not have an initializer.
2023-07-21 22:47:33 +01:00

958 lines
19 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"
)
// Node is implemented by types that represent a node.
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 is implemented by types that represent an Expression.
type Expression interface {
Node
expression()
}
// ArrayLiteral represents an array literal.
type ArrayLiteral struct {
LeftBracket file.Idx
RightBracket file.Idx
Value []Expression
}
// Idx0 implements Node.
func (al *ArrayLiteral) Idx0() file.Idx {
return al.LeftBracket
}
// Idx1 implements Node.
func (al *ArrayLiteral) Idx1() file.Idx {
return al.RightBracket + 1
}
// expression implements Expression.
func (*ArrayLiteral) expression() {}
// AssignExpression represents an assignment expression.
type AssignExpression struct {
Operator token.Token
Left Expression
Right Expression
}
// Idx0 implements Node.
func (ae *AssignExpression) Idx0() file.Idx {
return ae.Left.Idx0()
}
// Idx1 implements Node.
func (ae *AssignExpression) Idx1() file.Idx {
return ae.Right.Idx1()
}
// expression implements Expression.
func (*AssignExpression) expression() {}
// BadExpression represents a bad expression.
type BadExpression struct {
From file.Idx
To file.Idx
}
// Idx0 implements Node.
func (be *BadExpression) Idx0() file.Idx {
return be.From
}
// Idx1 implements Node.
func (be *BadExpression) Idx1() file.Idx {
return be.To
}
// expression implements Expression.
func (*BadExpression) expression() {}
// BinaryExpression represents a binary expression.
type BinaryExpression struct {
Operator token.Token
Left Expression
Right Expression
Comparison bool
}
// Idx0 implements Node.
func (be *BinaryExpression) Idx0() file.Idx {
return be.Left.Idx0()
}
// Idx1 implements Node.
func (be *BinaryExpression) Idx1() file.Idx {
return be.Right.Idx1()
}
// expression implements Expression.
func (*BinaryExpression) expression() {}
// BooleanLiteral represents a boolean expression.
type BooleanLiteral struct {
Idx file.Idx
Literal string
Value bool
}
// Idx0 implements Node.
func (bl *BooleanLiteral) Idx0() file.Idx {
return bl.Idx
}
// Idx1 implements Node.
func (bl *BooleanLiteral) Idx1() file.Idx {
return file.Idx(int(bl.Idx) + len(bl.Literal))
}
// expression implements Expression.
func (*BooleanLiteral) expression() {}
// BracketExpression represents a bracketed expression.
type BracketExpression struct {
Left Expression
Member Expression
LeftBracket file.Idx
RightBracket file.Idx
}
// Idx0 implements Node.
func (be *BracketExpression) Idx0() file.Idx {
return be.Left.Idx0()
}
// Idx1 implements Node.
func (be *BracketExpression) Idx1() file.Idx {
return be.RightBracket + 1
}
// expression implements Expression.
func (*BracketExpression) expression() {}
// CallExpression represents a call expression.
type CallExpression struct {
Callee Expression
LeftParenthesis file.Idx
ArgumentList []Expression
RightParenthesis file.Idx
}
// Idx0 implements Node.
func (ce *CallExpression) Idx0() file.Idx {
return ce.Callee.Idx0()
}
// Idx1 implements Node.
func (ce *CallExpression) Idx1() file.Idx {
return ce.RightParenthesis + 1
}
// expression implements Expression.
func (*CallExpression) expression() {}
// ConditionalExpression represents a conditional expression.
type ConditionalExpression struct {
Test Expression
Consequent Expression
Alternate Expression
}
// Idx0 implements Node.
func (ce *ConditionalExpression) Idx0() file.Idx {
return ce.Test.Idx0()
}
// Idx1 implements Node.
func (ce *ConditionalExpression) Idx1() file.Idx {
return ce.Alternate.Idx1()
}
// expression implements Expression.
func (*ConditionalExpression) expression() {}
// DotExpression represents a dot expression.
type DotExpression struct {
Left Expression
Identifier *Identifier
}
// Idx0 implements Node.
func (de *DotExpression) Idx0() file.Idx {
return de.Left.Idx0()
}
// Idx1 implements Node.
func (de *DotExpression) Idx1() file.Idx {
return de.Identifier.Idx1()
}
// expression implements Expression.
func (*DotExpression) expression() {}
// EmptyExpression represents an empty expression.
type EmptyExpression struct {
Begin file.Idx
End file.Idx
}
// Idx0 implements Node.
func (ee *EmptyExpression) Idx0() file.Idx {
return ee.Begin
}
// Idx1 implements Node.
func (ee *EmptyExpression) Idx1() file.Idx {
return ee.End
}
// expression implements Expression.
func (*EmptyExpression) expression() {}
// FunctionLiteral represents a function literal.
type FunctionLiteral struct {
Function file.Idx
Name *Identifier
ParameterList *ParameterList
Body Statement
Source string
DeclarationList []Declaration
}
// Idx0 implements Node.
func (fl *FunctionLiteral) Idx0() file.Idx {
return fl.Function
}
// Idx1 implements Node.
func (fl *FunctionLiteral) Idx1() file.Idx {
return fl.Body.Idx1()
}
// expression implements Expression.
func (*FunctionLiteral) expression() {}
// Identifier represents an identifier.
type Identifier struct {
Name string
Idx file.Idx
}
// Idx0 implements Node.
func (i *Identifier) Idx0() file.Idx {
return i.Idx
}
// Idx1 implements Node.
func (i *Identifier) Idx1() file.Idx {
return file.Idx(int(i.Idx) + len(i.Name))
}
// expression implements Expression.
func (*Identifier) expression() {}
// NewExpression represents a new expression.
type NewExpression struct {
New file.Idx
Callee Expression
LeftParenthesis file.Idx
ArgumentList []Expression
RightParenthesis file.Idx
}
// Idx0 implements Node.
func (ne *NewExpression) Idx0() file.Idx {
return ne.New
}
// Idx1 implements Node.
func (ne *NewExpression) Idx1() file.Idx {
if ne.RightParenthesis > 0 {
return ne.RightParenthesis + 1
}
return ne.Callee.Idx1()
}
// expression implements Expression.
func (*NewExpression) expression() {}
// NullLiteral represents a null literal.
type NullLiteral struct {
Idx file.Idx
Literal string
}
// Idx0 implements Node.
func (nl *NullLiteral) Idx0() file.Idx {
return nl.Idx
}
// Idx1 implements Node.
func (nl *NullLiteral) Idx1() file.Idx {
return file.Idx(int(nl.Idx) + 4)
}
// expression implements Expression.
func (*NullLiteral) expression() {}
// NumberLiteral represents a number literal.
type NumberLiteral struct {
Idx file.Idx
Literal string
Value interface{}
}
// Idx0 implements Node.
func (nl *NumberLiteral) Idx0() file.Idx {
return nl.Idx
}
// Idx1 implements Node.
func (nl *NumberLiteral) Idx1() file.Idx {
return file.Idx(int(nl.Idx) + len(nl.Literal))
}
// expression implements Expression.
func (*NumberLiteral) expression() {}
// ObjectLiteral represents an object literal.
type ObjectLiteral struct {
LeftBrace file.Idx
RightBrace file.Idx
Value []Property
}
// Idx0 implements Node.
func (ol *ObjectLiteral) Idx0() file.Idx {
return ol.LeftBrace
}
// Idx1 implements Node.
func (ol *ObjectLiteral) Idx1() file.Idx {
return ol.RightBrace + 1
}
// expression implements Expression.
func (*ObjectLiteral) expression() {}
// ParameterList represents a parameter list.
type ParameterList struct {
Opening file.Idx
List []*Identifier
Closing file.Idx
}
// Property represents a property.
type Property struct {
Key string
Kind string
Value Expression
}
// RegExpLiteral represents a regular expression literal.
type RegExpLiteral struct {
Idx file.Idx
Literal string
Pattern string
Flags string
Value string
}
// Idx0 implements Node.
func (rl *RegExpLiteral) Idx0() file.Idx {
return rl.Idx
}
// Idx1 implements Node.
func (rl *RegExpLiteral) Idx1() file.Idx {
return file.Idx(int(rl.Idx) + len(rl.Literal))
}
// expression implements Expression.
func (*RegExpLiteral) expression() {}
// SequenceExpression represents a sequence literal.
type SequenceExpression struct {
Sequence []Expression
}
// Idx0 implements Node.
func (se *SequenceExpression) Idx0() file.Idx {
return se.Sequence[0].Idx0()
}
// Idx1 implements Node.
func (se *SequenceExpression) Idx1() file.Idx {
return se.Sequence[len(se.Sequence)-1].Idx1()
}
// expression implements Expression.
func (*SequenceExpression) expression() {}
// StringLiteral represents a string literal.
type StringLiteral struct {
Idx file.Idx
Literal string
Value string
}
// Idx0 implements Node.
func (sl *StringLiteral) Idx0() file.Idx {
return sl.Idx
}
// Idx1 implements Node.
func (sl *StringLiteral) Idx1() file.Idx {
return file.Idx(int(sl.Idx) + len(sl.Literal))
}
// expression implements Expression.
func (*StringLiteral) expression() {}
// ThisExpression represents a this expression.
type ThisExpression struct {
Idx file.Idx
}
// Idx0 implements Node.
func (te *ThisExpression) Idx0() file.Idx {
return te.Idx
}
// Idx1 implements Node.
func (te *ThisExpression) Idx1() file.Idx {
return te.Idx + 4
}
// expression implements Expression.
func (*ThisExpression) expression() {}
// UnaryExpression represents a unary expression.
type UnaryExpression struct {
Operator token.Token
Idx file.Idx // If a prefix operation
Operand Expression
Postfix bool
}
// Idx0 implements Node.
func (ue *UnaryExpression) Idx0() file.Idx {
if ue.Postfix {
return ue.Operand.Idx0()
}
return ue.Idx
}
// Idx1 implements Node.
func (ue *UnaryExpression) Idx1() file.Idx {
if ue.Postfix {
return ue.Operand.Idx1() + 2 // ++ --
}
return ue.Operand.Idx1()
}
// expression implements Expression.
func (*UnaryExpression) expression() {}
// VariableExpression represents a variable expression.
type VariableExpression struct {
Name string
Idx file.Idx
Initializer Expression
}
// Idx0 implements Node.
func (ve *VariableExpression) Idx0() file.Idx {
return ve.Idx
}
// Idx1 implements Node.
func (ve *VariableExpression) Idx1() file.Idx {
if ve.Initializer == nil {
return file.Idx(int(ve.Idx) + len(ve.Name))
}
return ve.Initializer.Idx1()
}
// expression implements Expression.
func (*VariableExpression) expression() {}
// Statement is implemented by types which represent a statement.
type Statement interface {
Node
statement()
}
// BadStatement represents a bad statement.
type BadStatement struct {
From file.Idx
To file.Idx
}
// Idx0 implements Node.
func (bs *BadStatement) Idx0() file.Idx {
return bs.From
}
// Idx1 implements Node.
func (bs *BadStatement) Idx1() file.Idx {
return bs.To
}
// expression implements Statement.
func (*BadStatement) statement() {}
// BlockStatement represents a block statement.
type BlockStatement struct {
LeftBrace file.Idx
List []Statement
RightBrace file.Idx
}
// Idx0 implements Node.
func (bs *BlockStatement) Idx0() file.Idx {
return bs.LeftBrace
}
// Idx1 implements Node.
func (bs *BlockStatement) Idx1() file.Idx {
return bs.RightBrace + 1
}
// expression implements Statement.
func (*BlockStatement) statement() {}
// BranchStatement represents a branch statement.
type BranchStatement struct {
Idx file.Idx
Token token.Token
Label *Identifier
}
// Idx1 implements Node.
func (bs *BranchStatement) Idx1() file.Idx {
return bs.Idx
}
// Idx0 implements Node.
func (bs *BranchStatement) Idx0() file.Idx {
return bs.Idx
}
// expression implements Statement.
func (*BranchStatement) statement() {}
// CaseStatement represents a case statement.
type CaseStatement struct {
Case file.Idx
Test Expression
Consequent []Statement
}
// Idx0 implements Node.
func (cs *CaseStatement) Idx0() file.Idx {
return cs.Case
}
// Idx1 implements Node.
func (cs *CaseStatement) Idx1() file.Idx {
return cs.Consequent[len(cs.Consequent)-1].Idx1()
}
// expression implements Statement.
func (*CaseStatement) statement() {}
// CatchStatement represents a catch statement.
type CatchStatement struct {
Catch file.Idx
Parameter *Identifier
Body Statement
}
// Idx0 implements Node.
func (cs *CatchStatement) Idx0() file.Idx {
return cs.Catch
}
// Idx1 implements Node.
func (cs *CatchStatement) Idx1() file.Idx {
return cs.Body.Idx1()
}
// expression implements Statement.
func (*CatchStatement) statement() {}
// DebuggerStatement represents a debugger statement.
type DebuggerStatement struct {
Debugger file.Idx
}
// Idx0 implements Node.
func (ds *DebuggerStatement) Idx0() file.Idx {
return ds.Debugger
}
// Idx1 implements Node.
func (ds *DebuggerStatement) Idx1() file.Idx {
return ds.Debugger + 8
}
// expression implements Statement.
func (*DebuggerStatement) statement() {}
// DoWhileStatement represents a do while statement.
type DoWhileStatement struct {
Do file.Idx
Test Expression
Body Statement
}
// Idx0 implements Node.
func (dws *DoWhileStatement) Idx0() file.Idx {
return dws.Do
}
// Idx1 implements Node.
func (dws *DoWhileStatement) Idx1() file.Idx {
return dws.Test.Idx1()
}
// expression implements Statement.
func (*DoWhileStatement) statement() {}
// EmptyStatement represents a empty statement.
type EmptyStatement struct {
Semicolon file.Idx
}
// Idx0 implements Node.
func (es *EmptyStatement) Idx0() file.Idx {
return es.Semicolon
}
// Idx1 implements Node.
func (es *EmptyStatement) Idx1() file.Idx {
return es.Semicolon + 1
}
// expression implements Statement.
func (*EmptyStatement) statement() {}
// ExpressionStatement represents a expression statement.
type ExpressionStatement struct {
Expression Expression
}
// Idx0 implements Node.
func (es *ExpressionStatement) Idx0() file.Idx {
return es.Expression.Idx0()
}
// Idx1 implements Node.
func (es *ExpressionStatement) Idx1() file.Idx {
return es.Expression.Idx1()
}
// expression implements Statement.
func (*ExpressionStatement) statement() {}
// ForInStatement represents a for in statement.
type ForInStatement struct {
For file.Idx
Into Expression
Source Expression
Body Statement
}
// Idx0 implements Node.
func (fis *ForInStatement) Idx0() file.Idx {
return fis.For
}
// Idx1 implements Node.
func (fis *ForInStatement) Idx1() file.Idx {
return fis.Body.Idx1()
}
// expression implements Statement.
func (*ForInStatement) statement() {}
// ForStatement represents a for statement.
type ForStatement struct {
For file.Idx
Initializer Expression
Update Expression
Test Expression
Body Statement
}
// Idx0 implements Node.
func (fs *ForStatement) Idx0() file.Idx {
return fs.For
}
// Idx1 implements Node.
func (fs *ForStatement) Idx1() file.Idx {
return fs.Body.Idx1()
}
// expression implements Statement.
func (*ForStatement) statement() {}
// FunctionStatement represents a function statement.
type FunctionStatement struct {
Function *FunctionLiteral
}
// Idx0 implements Node.
func (fs *FunctionStatement) Idx0() file.Idx {
return fs.Function.Idx0()
}
// Idx1 implements Node.
func (fs *FunctionStatement) Idx1() file.Idx {
return fs.Function.Idx1()
}
// expression implements Statement.
func (*FunctionStatement) statement() {}
// IfStatement represents a if statement.
type IfStatement struct {
If file.Idx
Test Expression
Consequent Statement
Alternate Statement
}
// Idx0 implements Node.
func (is *IfStatement) Idx0() file.Idx {
return is.If
}
// Idx1 implements Node.
func (is *IfStatement) Idx1() file.Idx {
if is.Alternate != nil {
return is.Alternate.Idx1()
}
return is.Consequent.Idx1()
}
// expression implements Statement.
func (*IfStatement) statement() {}
// LabelledStatement represents a labelled statement.
type LabelledStatement struct {
Label *Identifier
Colon file.Idx
Statement Statement
}
// Idx0 implements Node.
func (ls *LabelledStatement) Idx0() file.Idx {
return ls.Label.Idx0()
}
// Idx1 implements Node.
func (ls *LabelledStatement) Idx1() file.Idx {
return ls.Colon + 1
}
// expression implements Statement.
func (*LabelledStatement) statement() {}
// ReturnStatement represents a return statement.
type ReturnStatement struct {
Return file.Idx
Argument Expression
}
// Idx0 implements Node.
func (rs *ReturnStatement) Idx0() file.Idx {
return rs.Return
}
// Idx1 implements Node.
func (rs *ReturnStatement) Idx1() file.Idx {
return rs.Return
}
// expression implements Statement.
func (*ReturnStatement) statement() {}
// SwitchStatement represents a switch statement.
type SwitchStatement struct {
Switch file.Idx
Discriminant Expression
Default int
Body []*CaseStatement
}
// Idx0 implements Node.
func (ss *SwitchStatement) Idx0() file.Idx {
return ss.Switch
}
// Idx1 implements Node.
func (ss *SwitchStatement) Idx1() file.Idx {
return ss.Body[len(ss.Body)-1].Idx1()
}
// expression implements Statement.
func (*SwitchStatement) statement() {}
// ThrowStatement represents a throw statement.
type ThrowStatement struct {
Throw file.Idx
Argument Expression
}
// Idx0 implements Node.
func (ts *ThrowStatement) Idx0() file.Idx {
return ts.Throw
}
// Idx1 implements Node.
func (ts *ThrowStatement) Idx1() file.Idx {
return ts.Throw
}
// expression implements Statement.
func (*ThrowStatement) statement() {}
// TryStatement represents a try statement.
type TryStatement struct {
Try file.Idx
Body Statement
Catch *CatchStatement
Finally Statement
}
// Idx0 implements Node.
func (ts *TryStatement) Idx0() file.Idx {
return ts.Try
}
// Idx1 implements Node.
func (ts *TryStatement) Idx1() file.Idx {
return ts.Try
}
// expression implements Statement.
func (*TryStatement) statement() {}
// VariableStatement represents a variable statement.
type VariableStatement struct {
Var file.Idx
List []Expression
}
// Idx0 implements Node.
func (vs *VariableStatement) Idx0() file.Idx {
return vs.Var
}
// Idx1 implements Node.
func (vs *VariableStatement) Idx1() file.Idx {
return vs.List[len(vs.List)-1].Idx1()
}
// expression implements Statement.
func (*VariableStatement) statement() {}
// WhileStatement represents a while statement.
type WhileStatement struct {
While file.Idx
Test Expression
Body Statement
}
// Idx0 implements Node.
func (ws *WhileStatement) Idx0() file.Idx {
return ws.While
}
// Idx1 implements Node.
func (ws *WhileStatement) Idx1() file.Idx {
return ws.Body.Idx1()
}
// expression implements Statement.
func (*WhileStatement) statement() {}
// WithStatement represents a with statement.
type WithStatement struct {
With file.Idx
Object Expression
Body Statement
}
// Idx0 implements Node.
func (ws *WithStatement) Idx0() file.Idx {
return ws.With
}
// Idx1 implements Node.
func (ws *WithStatement) Idx1() file.Idx {
return ws.Body.Idx1()
}
// expression implements Statement.
func (*WithStatement) statement() {}
// Declaration is implemented by type which represent declarations.
type Declaration interface {
declaration()
}
// FunctionDeclaration represents a function declaration.
type FunctionDeclaration struct {
Function *FunctionLiteral
}
func (*FunctionDeclaration) declaration() {}
// VariableDeclaration represents a variable declaration.
type VariableDeclaration struct {
Var file.Idx
List []*VariableExpression
}
// declaration implements Declaration.
func (*VariableDeclaration) declaration() {}
// Program represents a full program.
type Program struct {
Body []Statement
DeclarationList []Declaration
File *file.File
Comments CommentMap
}
// Idx0 implements Node.
func (p *Program) Idx0() file.Idx {
return p.Body[0].Idx0()
}
// Idx1 implements Node.
func (p *Program) Idx1() file.Idx {
return p.Body[len(p.Body)-1].Idx1()
}