forked from jshiffer/matterbridge
350 lines
7.1 KiB
Go
350 lines
7.1 KiB
Go
|
package parser
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
|
||
|
"github.com/d5/tengo/v2/token"
|
||
|
)
|
||
|
|
||
|
// Stmt represents a statement in the AST.
|
||
|
type Stmt interface {
|
||
|
Node
|
||
|
stmtNode()
|
||
|
}
|
||
|
|
||
|
// AssignStmt represents an assignment statement.
|
||
|
type AssignStmt struct {
|
||
|
LHS []Expr
|
||
|
RHS []Expr
|
||
|
Token token.Token
|
||
|
TokenPos Pos
|
||
|
}
|
||
|
|
||
|
func (s *AssignStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *AssignStmt) Pos() Pos {
|
||
|
return s.LHS[0].Pos()
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *AssignStmt) End() Pos {
|
||
|
return s.RHS[len(s.RHS)-1].End()
|
||
|
}
|
||
|
|
||
|
func (s *AssignStmt) String() string {
|
||
|
var lhs, rhs []string
|
||
|
for _, e := range s.LHS {
|
||
|
lhs = append(lhs, e.String())
|
||
|
}
|
||
|
for _, e := range s.RHS {
|
||
|
rhs = append(rhs, e.String())
|
||
|
}
|
||
|
return strings.Join(lhs, ", ") + " " + s.Token.String() +
|
||
|
" " + strings.Join(rhs, ", ")
|
||
|
}
|
||
|
|
||
|
// BadStmt represents a bad statement.
|
||
|
type BadStmt struct {
|
||
|
From Pos
|
||
|
To Pos
|
||
|
}
|
||
|
|
||
|
func (s *BadStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *BadStmt) Pos() Pos {
|
||
|
return s.From
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *BadStmt) End() Pos {
|
||
|
return s.To
|
||
|
}
|
||
|
|
||
|
func (s *BadStmt) String() string {
|
||
|
return "<bad statement>"
|
||
|
}
|
||
|
|
||
|
// BlockStmt represents a block statement.
|
||
|
type BlockStmt struct {
|
||
|
Stmts []Stmt
|
||
|
LBrace Pos
|
||
|
RBrace Pos
|
||
|
}
|
||
|
|
||
|
func (s *BlockStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *BlockStmt) Pos() Pos {
|
||
|
return s.LBrace
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *BlockStmt) End() Pos {
|
||
|
return s.RBrace + 1
|
||
|
}
|
||
|
|
||
|
func (s *BlockStmt) String() string {
|
||
|
var list []string
|
||
|
for _, e := range s.Stmts {
|
||
|
list = append(list, e.String())
|
||
|
}
|
||
|
return "{" + strings.Join(list, "; ") + "}"
|
||
|
}
|
||
|
|
||
|
// BranchStmt represents a branch statement.
|
||
|
type BranchStmt struct {
|
||
|
Token token.Token
|
||
|
TokenPos Pos
|
||
|
Label *Ident
|
||
|
}
|
||
|
|
||
|
func (s *BranchStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *BranchStmt) Pos() Pos {
|
||
|
return s.TokenPos
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *BranchStmt) End() Pos {
|
||
|
if s.Label != nil {
|
||
|
return s.Label.End()
|
||
|
}
|
||
|
|
||
|
return Pos(int(s.TokenPos) + len(s.Token.String()))
|
||
|
}
|
||
|
|
||
|
func (s *BranchStmt) String() string {
|
||
|
var label string
|
||
|
if s.Label != nil {
|
||
|
label = " " + s.Label.Name
|
||
|
}
|
||
|
return s.Token.String() + label
|
||
|
}
|
||
|
|
||
|
// EmptyStmt represents an empty statement.
|
||
|
type EmptyStmt struct {
|
||
|
Semicolon Pos
|
||
|
Implicit bool
|
||
|
}
|
||
|
|
||
|
func (s *EmptyStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *EmptyStmt) Pos() Pos {
|
||
|
return s.Semicolon
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *EmptyStmt) End() Pos {
|
||
|
if s.Implicit {
|
||
|
return s.Semicolon
|
||
|
}
|
||
|
return s.Semicolon + 1
|
||
|
}
|
||
|
|
||
|
func (s *EmptyStmt) String() string {
|
||
|
return ";"
|
||
|
}
|
||
|
|
||
|
// ExportStmt represents an export statement.
|
||
|
type ExportStmt struct {
|
||
|
ExportPos Pos
|
||
|
Result Expr
|
||
|
}
|
||
|
|
||
|
func (s *ExportStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *ExportStmt) Pos() Pos {
|
||
|
return s.ExportPos
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *ExportStmt) End() Pos {
|
||
|
return s.Result.End()
|
||
|
}
|
||
|
|
||
|
func (s *ExportStmt) String() string {
|
||
|
return "export " + s.Result.String()
|
||
|
}
|
||
|
|
||
|
// ExprStmt represents an expression statement.
|
||
|
type ExprStmt struct {
|
||
|
Expr Expr
|
||
|
}
|
||
|
|
||
|
func (s *ExprStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *ExprStmt) Pos() Pos {
|
||
|
return s.Expr.Pos()
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *ExprStmt) End() Pos {
|
||
|
return s.Expr.End()
|
||
|
}
|
||
|
|
||
|
func (s *ExprStmt) String() string {
|
||
|
return s.Expr.String()
|
||
|
}
|
||
|
|
||
|
// ForInStmt represents a for-in statement.
|
||
|
type ForInStmt struct {
|
||
|
ForPos Pos
|
||
|
Key *Ident
|
||
|
Value *Ident
|
||
|
Iterable Expr
|
||
|
Body *BlockStmt
|
||
|
}
|
||
|
|
||
|
func (s *ForInStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *ForInStmt) Pos() Pos {
|
||
|
return s.ForPos
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *ForInStmt) End() Pos {
|
||
|
return s.Body.End()
|
||
|
}
|
||
|
|
||
|
func (s *ForInStmt) String() string {
|
||
|
if s.Value != nil {
|
||
|
return "for " + s.Key.String() + ", " + s.Value.String() +
|
||
|
" in " + s.Iterable.String() + " " + s.Body.String()
|
||
|
}
|
||
|
return "for " + s.Key.String() + " in " + s.Iterable.String() +
|
||
|
" " + s.Body.String()
|
||
|
}
|
||
|
|
||
|
// ForStmt represents a for statement.
|
||
|
type ForStmt struct {
|
||
|
ForPos Pos
|
||
|
Init Stmt
|
||
|
Cond Expr
|
||
|
Post Stmt
|
||
|
Body *BlockStmt
|
||
|
}
|
||
|
|
||
|
func (s *ForStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *ForStmt) Pos() Pos {
|
||
|
return s.ForPos
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *ForStmt) End() Pos {
|
||
|
return s.Body.End()
|
||
|
}
|
||
|
|
||
|
func (s *ForStmt) String() string {
|
||
|
var init, cond, post string
|
||
|
if s.Init != nil {
|
||
|
init = s.Init.String()
|
||
|
}
|
||
|
if s.Cond != nil {
|
||
|
cond = s.Cond.String() + " "
|
||
|
}
|
||
|
if s.Post != nil {
|
||
|
post = s.Post.String()
|
||
|
}
|
||
|
|
||
|
if init != "" || post != "" {
|
||
|
return "for " + init + " ; " + cond + " ; " + post + s.Body.String()
|
||
|
}
|
||
|
return "for " + cond + s.Body.String()
|
||
|
}
|
||
|
|
||
|
// IfStmt represents an if statement.
|
||
|
type IfStmt struct {
|
||
|
IfPos Pos
|
||
|
Init Stmt
|
||
|
Cond Expr
|
||
|
Body *BlockStmt
|
||
|
Else Stmt // else branch; or nil
|
||
|
}
|
||
|
|
||
|
func (s *IfStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *IfStmt) Pos() Pos {
|
||
|
return s.IfPos
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *IfStmt) End() Pos {
|
||
|
if s.Else != nil {
|
||
|
return s.Else.End()
|
||
|
}
|
||
|
return s.Body.End()
|
||
|
}
|
||
|
|
||
|
func (s *IfStmt) String() string {
|
||
|
var initStmt, elseStmt string
|
||
|
if s.Init != nil {
|
||
|
initStmt = s.Init.String() + "; "
|
||
|
}
|
||
|
if s.Else != nil {
|
||
|
elseStmt = " else " + s.Else.String()
|
||
|
}
|
||
|
return "if " + initStmt + s.Cond.String() + " " +
|
||
|
s.Body.String() + elseStmt
|
||
|
}
|
||
|
|
||
|
// IncDecStmt represents increment or decrement statement.
|
||
|
type IncDecStmt struct {
|
||
|
Expr Expr
|
||
|
Token token.Token
|
||
|
TokenPos Pos
|
||
|
}
|
||
|
|
||
|
func (s *IncDecStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *IncDecStmt) Pos() Pos {
|
||
|
return s.Expr.Pos()
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *IncDecStmt) End() Pos {
|
||
|
return Pos(int(s.TokenPos) + 2)
|
||
|
}
|
||
|
|
||
|
func (s *IncDecStmt) String() string {
|
||
|
return s.Expr.String() + s.Token.String()
|
||
|
}
|
||
|
|
||
|
// ReturnStmt represents a return statement.
|
||
|
type ReturnStmt struct {
|
||
|
ReturnPos Pos
|
||
|
Result Expr
|
||
|
}
|
||
|
|
||
|
func (s *ReturnStmt) stmtNode() {}
|
||
|
|
||
|
// Pos returns the position of first character belonging to the node.
|
||
|
func (s *ReturnStmt) Pos() Pos {
|
||
|
return s.ReturnPos
|
||
|
}
|
||
|
|
||
|
// End returns the position of first character immediately after the node.
|
||
|
func (s *ReturnStmt) End() Pos {
|
||
|
if s.Result != nil {
|
||
|
return s.Result.End()
|
||
|
}
|
||
|
return s.ReturnPos + 6
|
||
|
}
|
||
|
|
||
|
func (s *ReturnStmt) String() string {
|
||
|
if s.Result != nil {
|
||
|
return "return " + s.Result.String()
|
||
|
}
|
||
|
return "return"
|
||
|
}
|