Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make node types more strict #23

Merged
merged 5 commits into from Dec 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 57 additions & 2 deletions ast/node.go
Expand Up @@ -14,17 +14,19 @@ type Node interface {
// Statement is the interface for statement (Ex command or Comment).
type Statement interface {
Node
stmtNode()
}

// ExCommand is the interface for Ex-command.
type ExCommand interface {
Node
Statement
Cmd() Cmd
}

// Expr is the interface for expression.
type Expr interface {
Node
exprNode()
}

// File node represents a Vim script source file.
Expand All @@ -39,6 +41,7 @@ func (f *File) Pos() Pos { return f.Start }

// vimlparser: COMMENT .str
type Comment struct {
Statement
Quote Pos // position of `"` starting the comment
Text string // comment text (excluding '\n')
}
Expand Down Expand Up @@ -480,7 +483,7 @@ type CurlyName struct {
func (c *CurlyName) Pos() Pos { return c.CurlyName }

type CurlyNamePart interface {
Node
Expr
IsCurlyExpr() bool
}

Expand Down Expand Up @@ -522,3 +525,55 @@ type LambdaExpr struct {
}

func (i *LambdaExpr) Pos() Pos { return i.Lcurlybrace }

// stmtNode() ensures that only ExComamnd and Comment nodes can be assigned to
// an Statement.
//
func (*Break) stmtNode() {}
func (*Catch) stmtNode() {}
func (*Continue) stmtNode() {}
func (DelFunction) stmtNode() {}
func (*EchoCmd) stmtNode() {}
func (*Echohl) stmtNode() {}
func (*Else) stmtNode() {}
func (*ElseIf) stmtNode() {}
func (*EndFor) stmtNode() {}
func (EndFunction) stmtNode() {}
func (*EndIf) stmtNode() {}
func (*EndTry) stmtNode() {}
func (*EndWhile) stmtNode() {}
func (*ExCall) stmtNode() {}
func (Excmd) stmtNode() {}
func (*Execute) stmtNode() {}
func (*Finally) stmtNode() {}
func (*For) stmtNode() {}
func (Function) stmtNode() {}
func (*If) stmtNode() {}
func (*Let) stmtNode() {}
func (*LockVar) stmtNode() {}
func (*Return) stmtNode() {}
func (*Throw) stmtNode() {}
func (*Try) stmtNode() {}
func (*UnLet) stmtNode() {}
func (*UnLockVar) stmtNode() {}
func (*While) stmtNode() {}

func (*Comment) stmtNode() {}

// exprNode() ensures that only expression nodes can be assigned to an Expr.
//
func (*TernaryExpr) exprNode() {}
func (*BinaryExpr) exprNode() {}
func (*UnaryExpr) exprNode() {}
func (*SubscriptExpr) exprNode() {}
func (*SliceExpr) exprNode() {}
func (*CallExpr) exprNode() {}
func (*DotExpr) exprNode() {}
func (*BasicLit) exprNode() {}
func (*List) exprNode() {}
func (*Dict) exprNode() {}
func (*CurlyName) exprNode() {}
func (*CurlyNameLit) exprNode() {}
func (*CurlyNameExpr) exprNode() {}
func (*Ident) exprNode() {}
func (*LambdaExpr) exprNode() {}
83 changes: 45 additions & 38 deletions go/export.go
Expand Up @@ -7,12 +7,14 @@ import (
"github.com/haya14busa/go-vimlparser/token"
)

func (self *VimLParser) Parse(reader *StringReader, filename string) ast.Node {
return newAstNode(self.parse(reader), filename)
// Parse parses Vim script in reader and returns Node.
func (p *VimLParser) Parse(reader *StringReader, filename string) ast.Node {
return newAstNode(p.parse(reader), filename)
}

func (self *ExprParser) Parse() ast.Node {
return newAstNode(self.parse(), "")
// Parse parses Vim script expression.
func (p *ExprParser) Parse() ast.Expr {
return newExprNode(p.parse(), "")
}

// ----
Expand Down Expand Up @@ -65,7 +67,7 @@ func newAstNode(n *VimNode, filename string) ast.Node {
Func: pos,
ExArg: newExArg(*n.ea, filename),
Body: newBody(*n, filename),
Name: newAstNode(n.left, filename),
Name: newExprNode(n.left, filename),
Params: newIdents(*n, filename),
Attr: attr,
EndFunction: newAstNode(n.endfunction, filename).(*ast.EndFunction),
Expand All @@ -81,14 +83,14 @@ func newAstNode(n *VimNode, filename string) ast.Node {
return &ast.DelFunction{
DelFunc: pos,
ExArg: newExArg(*n.ea, filename),
Name: newAstNode(n.left, filename),
Name: newExprNode(n.left, filename),
}

case NODE_RETURN:
return &ast.Return{
Return: pos,
ExArg: newExArg(*n.ea, filename),
Result: newAstNode(n.left, filename),
Result: newExprNode(n.left, filename),
}

case NODE_EXCALL:
Expand All @@ -103,10 +105,10 @@ func newAstNode(n *VimNode, filename string) ast.Node {
Let: pos,
ExArg: newExArg(*n.ea, filename),
Op: n.op,
Left: newAstNode(n.left, filename),
Left: newExprNode(n.left, filename),
List: newList(*n, filename),
Rest: newAstNode(n.rest, filename),
Right: newAstNode(n.right, filename),
Rest: newExprNode(n.rest, filename),
Right: newExprNode(n.right, filename),
}

case NODE_UNLET:
Expand Down Expand Up @@ -150,7 +152,7 @@ func newAstNode(n *VimNode, filename string) ast.Node {
If: pos,
ExArg: newExArg(*n.ea, filename),
Body: newBody(*n, filename),
Condition: newAstNode(n.cond, filename),
Condition: newExprNode(n.cond, filename),
ElseIf: elifs,
Else: els,
EndIf: newAstNode(n.endif, filename).(*ast.EndIf),
Expand All @@ -161,7 +163,7 @@ func newAstNode(n *VimNode, filename string) ast.Node {
ElseIf: pos,
ExArg: newExArg(*n.ea, filename),
Body: newBody(*n, filename),
Condition: newAstNode(n.cond, filename),
Condition: newExprNode(n.cond, filename),
}

case NODE_ELSE:
Expand All @@ -182,7 +184,7 @@ func newAstNode(n *VimNode, filename string) ast.Node {
While: pos,
ExArg: newExArg(*n.ea, filename),
Body: newBody(*n, filename),
Condition: newAstNode(n.cond, filename),
Condition: newExprNode(n.cond, filename),
EndWhile: newAstNode(n.endwhile, filename).(*ast.EndWhile),
}

Expand All @@ -197,10 +199,10 @@ func newAstNode(n *VimNode, filename string) ast.Node {
For: pos,
ExArg: newExArg(*n.ea, filename),
Body: newBody(*n, filename),
Left: newAstNode(n.left, filename),
Left: newExprNode(n.left, filename),
List: newList(*n, filename),
Rest: newAstNode(n.rest, filename),
Right: newAstNode(n.right, filename),
Rest: newExprNode(n.rest, filename),
Right: newExprNode(n.right, filename),
EndFor: newAstNode(n.endfor, filename).(*ast.EndFor),
}

Expand Down Expand Up @@ -270,7 +272,7 @@ func newAstNode(n *VimNode, filename string) ast.Node {
return &ast.Throw{
Throw: pos,
ExArg: newExArg(*n.ea, filename),
Expr: newAstNode(n.left, filename),
Expr: newExprNode(n.left, filename),
}

case NODE_ECHO, NODE_ECHON, NODE_ECHOMSG, NODE_ECHOERR:
Expand Down Expand Up @@ -298,9 +300,9 @@ func newAstNode(n *VimNode, filename string) ast.Node {
case NODE_TERNARY:
return &ast.TernaryExpr{
Ternary: pos,
Condition: newAstNode(n.cond, filename),
Left: newAstNode(n.left, filename),
Right: newAstNode(n.right, filename),
Condition: newExprNode(n.cond, filename),
Left: newExprNode(n.left, filename),
Right: newExprNode(n.right, filename),
}

case NODE_OR, NODE_AND, NODE_EQUAL, NODE_EQUALCI, NODE_EQUALCS,
Expand All @@ -313,44 +315,44 @@ func newAstNode(n *VimNode, filename string) ast.Node {
NODE_ISNOTCI, NODE_ISNOTCS, NODE_ADD, NODE_SUBTRACT, NODE_CONCAT,
NODE_MULTIPLY, NODE_DIVIDE, NODE_REMAINDER:
return &ast.BinaryExpr{
Left: newAstNode(n.left, filename),
Left: newExprNode(n.left, filename),
OpPos: pos,
Op: opToken(n.type_),
Right: newAstNode(n.right, filename),
Right: newExprNode(n.right, filename),
}

case NODE_NOT, NODE_MINUS, NODE_PLUS:
return &ast.UnaryExpr{
OpPos: pos,
Op: opToken(n.type_),
X: newAstNode(n.left, filename),
X: newExprNode(n.left, filename),
}

case NODE_SUBSCRIPT:
return &ast.SubscriptExpr{
Lbrack: pos,
Left: newAstNode(n.left, filename),
Right: newAstNode(n.right, filename),
Left: newExprNode(n.left, filename),
Right: newExprNode(n.right, filename),
}

case NODE_SLICE:
return &ast.SliceExpr{
Lbrack: pos,
X: newAstNode(n.left, filename),
Low: newAstNode(n.rlist[0], filename),
High: newAstNode(n.rlist[1], filename),
X: newExprNode(n.left, filename),
Low: newExprNode(n.rlist[0], filename),
High: newExprNode(n.rlist[1], filename),
}

case NODE_CALL:
return &ast.CallExpr{
Lparen: pos,
Fun: newAstNode(n.left, filename),
Fun: newExprNode(n.left, filename),
Args: newRlist(*n, filename),
}

case NODE_DOT:
return &ast.DotExpr{
Left: newAstNode(n.left, filename),
Left: newExprNode(n.left, filename),
Dot: pos,
Right: newAstNode(n.right, filename).(*ast.Ident),
}
Expand Down Expand Up @@ -378,8 +380,8 @@ func newAstNode(n *VimNode, filename string) ast.Node {
kvs := make([]ast.KeyValue, 0, len(entries))
for _, nn := range entries {
kv := nn.([]interface{})
k := newAstNode(kv[0].(*VimNode), filename)
v := newAstNode(kv[1].(*VimNode), filename)
k := newExprNode(kv[0].(*VimNode), filename)
v := newExprNode(kv[1].(*VimNode), filename)
kvs = append(kvs, ast.KeyValue{Key: k, Value: v})
}
return &ast.Dict{
Expand Down Expand Up @@ -434,20 +436,25 @@ func newAstNode(n *VimNode, filename string) ast.Node {
n := n.value.(*VimNode)
return &ast.CurlyNameExpr{
CurlyNameExpr: pos,
Value: newAstNode(n, filename),
Value: newExprNode(n, filename),
}

case NODE_LAMBDA:
return &ast.LambdaExpr{
Lcurlybrace: pos,
Params: newIdents(*n, filename),
Expr: newAstNode(n.left, filename),
Expr: newExprNode(n.left, filename),
}

}
panic(fmt.Errorf("Unknown node type: %v, node: %v", n.type_, n))
}

func newExprNode(n *VimNode, filename string) ast.Expr {
node, _ := newAstNode(n, filename).(ast.Expr)
return node
}

func newPos(p *pos, filename string) *ast.Pos {
if p == nil {
return nil
Expand Down Expand Up @@ -508,7 +515,7 @@ func newBody(n VimNode, filename string) []ast.Statement {
}
for _, node := range n.body {
if node != nil { // conservative
body = append(body, newAstNode(node, filename))
body = append(body, newAstNode(node, filename).(ast.Statement))
}
}
return body
Expand All @@ -534,7 +541,7 @@ func newRlist(n VimNode, filename string) []ast.Expr {
}
for _, node := range n.rlist {
if node != nil { // conservative
exprs = append(exprs, newAstNode(node, filename))
exprs = append(exprs, newExprNode(node, filename))
}
}
return exprs
Expand All @@ -547,7 +554,7 @@ func newList(n VimNode, filename string) []ast.Expr {
}
for _, node := range n.list {
if node != nil { // conservative
list = append(list, newAstNode(node, filename))
list = append(list, newExprNode(node, filename))
}
}
return list
Expand All @@ -557,7 +564,7 @@ func newValues(n VimNode, filename string) []ast.Expr {
var values []ast.Expr
for _, v := range n.value.([]interface{}) {
n := v.(*VimNode)
values = append(values, newAstNode(n, filename))
values = append(values, newExprNode(n, filename))
}
return values
}
Expand Down