summaryrefslogtreecommitdiff
path: root/parser/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'parser/parse.go')
-rw-r--r--parser/parse.go51
1 files changed, 40 insertions, 11 deletions
diff --git a/parser/parse.go b/parser/parse.go
index 08fbdbd..ca89467 100644
--- a/parser/parse.go
+++ b/parser/parse.go
@@ -10,6 +10,7 @@ const (
Call
Index
Decl
+ MultiOp
)
type NodeSpec struct {
@@ -23,21 +24,22 @@ type Parser struct {
Spec map[string]NodeSpec
}
-func (p *Parser) Parse(src string) (n []*Node, err error) {
+func (p *Parser) Parse(src string, ctx *Node) (nodes []*Node, err error) {
tokens, err := p.Scan(src)
if err != nil {
return
}
- return p.ParseTokens(tokens)
+ return p.ParseTokens(tokens, ctx)
}
-func (p *Parser) ParseTokens(tokens []scanner.Token) (roots []*Node, err error) {
+func (p *Parser) ParseTokens(tokens []*scanner.Token, ctx *Node) (nodes []*Node, err error) {
// TODO: error handling.
var root *Node // current root node
var expr *Node // current expression root node
var prev, c *Node // previous and current nodes
var lce *Node // last complete expression node
unaryOp := map[*Node]bool{} // unaryOp indicates if a node is an unary operator.
+ prevToken := map[*Node]*scanner.Token{}
for i, t := range tokens {
prev = c
@@ -45,6 +47,9 @@ func (p *Parser) ParseTokens(tokens []scanner.Token) (roots []*Node, err error)
Token: t,
Kind: p.Spec[t.Name()].Kind,
}
+ if i > 0 {
+ prevToken[c] = tokens[i-1]
+ }
if c.Kind == Comment {
continue
}
@@ -90,7 +95,7 @@ func (p *Parser) ParseTokens(tokens []scanner.Token) (roots []*Node, err error)
}
tcont := t.Content()
s := tcont[t.Start() : len(tcont)-t.End()]
- n2, err := p.Parse(s)
+ n2, err := p.Parse(s, c)
if err != nil {
return nil, err
}
@@ -99,10 +104,12 @@ func (p *Parser) ParseTokens(tokens []scanner.Token) (roots []*Node, err error)
// Process the end of an expression or a statement.
if t.IsSeparator() {
- if expr != nil && p.hasProp(root, Stmt) {
+ if t.Content() == "," && ctx.Kind != BlockParen {
+ // ignore comma separator in field lists
+ } else if expr != nil && p.hasProp(root, Stmt) {
root.Child = append(root.Child, expr)
if p.hasProp(expr, ExprSep) {
- roots = append(roots, root)
+ nodes = append(nodes, root)
root = nil
}
expr = nil
@@ -110,7 +117,7 @@ func (p *Parser) ParseTokens(tokens []scanner.Token) (roots []*Node, err error)
if expr != nil {
root = expr
}
- roots = append(roots, root)
+ nodes = append(nodes, root)
expr = nil
root = nil
}
@@ -190,9 +197,31 @@ func (p *Parser) ParseTokens(tokens []scanner.Token) (roots []*Node, err error)
root = expr
}
if root != nil {
- roots = append(roots, root)
+ // /*
+ if p.hasProp(root, MultiOp) {
+ for {
+ if !p.fixMultiOp(root, prevToken) {
+ break
+ }
+ }
+ }
+ // */
+ nodes = append(nodes, root)
+ }
+ return nodes, err
+}
+
+func (p *Parser) fixMultiOp(root *Node, prevToken map[*Node]*scanner.Token) bool {
+ for i, c := range root.Child {
+ for j, cc := range c.Child {
+ if pt := prevToken[cc]; pt != nil && pt.Content() == "," {
+ c.RemoveChild(j)
+ root.InsertChild(cc, i)
+ return true
+ }
+ }
}
- return roots, err
+ return false
}
func (p *Parser) hasProp(n *Node, prop uint) bool { return p.Spec[n.Name()].Flags&prop != 0 }
@@ -202,7 +231,7 @@ func (p *Parser) isExpr(n *Node) bool { return !p.isStatement(n) &&
func (p *Parser) isSep(n *Node) bool { return n.Token.Kind() == scanner.Separator }
func (p *Parser) IsBlock(n *Node) bool { return n.Token.Kind() == scanner.Block }
-func (p *Parser) precedenceToken(t scanner.Token) int {
+func (p *Parser) precedenceToken(t *scanner.Token) int {
s := t.Content()
if l := t.Start(); l > 0 {
s = s[:l]
@@ -210,6 +239,6 @@ func (p *Parser) precedenceToken(t scanner.Token) int {
return p.Spec[s].Order
}
-func (p *Parser) canCallToken(t scanner.Token) bool {
+func (p *Parser) canCallToken(t *scanner.Token) bool {
return p.precedenceToken(t) == 0 || p.Spec[t.Name()].Flags&Call != 0
}