From 8df930d4f0de3b52c8a55f5978673f1839097623 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 3 Dec 2016 18:29:55 +0900 Subject: [PATCH 1/5] make Expr sum type --- ast/node.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ast/node.go b/ast/node.go index 8e289fd..8150767 100644 --- a/ast/node.go +++ b/ast/node.go @@ -25,6 +25,7 @@ type ExCommand interface { // Expr is the interface for expression. type Expr interface { Node + exprNode() } // File node represents a Vim script source file. @@ -480,7 +481,7 @@ type CurlyName struct { func (c *CurlyName) Pos() Pos { return c.CurlyName } type CurlyNamePart interface { - Node + Expr IsCurlyExpr() bool } @@ -522,3 +523,22 @@ type LambdaExpr struct { } func (i *LambdaExpr) Pos() Pos { return i.Lcurlybrace } + +// 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 (*KeyValue) exprNode() {} +func (*CurlyName) exprNode() {} +func (*CurlyNameLit) exprNode() {} +func (*CurlyNameExpr) exprNode() {} +func (*Ident) exprNode() {} +func (*LambdaExpr) exprNode() {} From 3827bd111cc938acdcadb7f6d415e7f6a93bfd64 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 3 Dec 2016 18:51:40 +0900 Subject: [PATCH 2/5] make Statement sum type --- ast/node.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/ast/node.go b/ast/node.go index 8150767..50a74f8 100644 --- a/ast/node.go +++ b/ast/node.go @@ -14,12 +14,14 @@ 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 Cmd() Cmd + stmtNode() } // Expr is the interface for expression. @@ -524,6 +526,40 @@ 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() {} From feef6061d64272989eb766641ffd433ec7972c05 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 3 Dec 2016 18:51:58 +0900 Subject: [PATCH 3/5] fix node exportation --- go/export.go | 77 ++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/go/export.go b/go/export.go index 6a954f4..208c66c 100644 --- a/go/export.go +++ b/go/export.go @@ -11,8 +11,8 @@ func (self *VimLParser) Parse(reader *StringReader, filename string) ast.Node { return newAstNode(self.parse(reader), filename) } -func (self *ExprParser) Parse() ast.Node { - return newAstNode(self.parse(), "") +func (self *ExprParser) Parse() ast.Expr { + return newExprNode(self.parse(), "") } // ---- @@ -65,7 +65,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), @@ -81,14 +81,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: @@ -103,10 +103,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: @@ -150,7 +150,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), @@ -161,7 +161,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: @@ -182,7 +182,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), } @@ -197,10 +197,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), } @@ -270,7 +270,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: @@ -298,9 +298,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, @@ -313,44 +313,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), } @@ -378,8 +378,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{ @@ -434,20 +434,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 @@ -508,7 +513,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 @@ -534,7 +539,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 @@ -547,7 +552,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 @@ -557,7 +562,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 } From 4d6ec0f5850a872c37fa38d1f9967972d9195463 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 3 Dec 2016 23:44:30 +0900 Subject: [PATCH 4/5] fix unused --- ast/node.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ast/node.go b/ast/node.go index 50a74f8..e51f4b1 100644 --- a/ast/node.go +++ b/ast/node.go @@ -19,9 +19,8 @@ type Statement interface { // ExCommand is the interface for Ex-command. type ExCommand interface { - Node + Statement Cmd() Cmd - stmtNode() } // Expr is the interface for expression. @@ -42,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') } @@ -572,7 +572,6 @@ func (*DotExpr) exprNode() {} func (*BasicLit) exprNode() {} func (*List) exprNode() {} func (*Dict) exprNode() {} -func (*KeyValue) exprNode() {} func (*CurlyName) exprNode() {} func (*CurlyNameLit) exprNode() {} func (*CurlyNameExpr) exprNode() {} From 253f161f22e60d73570ca65908b39c265708358b Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 3 Dec 2016 23:46:02 +0900 Subject: [PATCH 5/5] add comment --- go/export.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/go/export.go b/go/export.go index 208c66c..8b96b22 100644 --- a/go/export.go +++ b/go/export.go @@ -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.Expr { - return newExprNode(self.parse(), "") +// Parse parses Vim script expression. +func (p *ExprParser) Parse() ast.Expr { + return newExprNode(p.parse(), "") } // ----