Skip to content

Commit

Permalink
add node stack, addexpr
Browse files Browse the repository at this point in the history
  • Loading branch information
jmoiron committed May 24, 2014
1 parent 694e70c commit 7510939
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 8 deletions.
46 changes: 46 additions & 0 deletions neo/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,34 @@ const (
NodeFloat
NodeInteger
NodeString
NodeAdd
NodeMul
)

// This is a stack of nodes starting at a position. It has the default NodeType
// but should never end up in the AST; it's use is in implementing order of
// operations for expressions
type nodeStack struct {
NodeType
Pos
Nodes []Node
}

func newStack(pos Pos) *nodeStack {
return &nodeStack{Pos: pos}
}

func (n *nodeStack) len() int { return len(n.Nodes) }
func (n *nodeStack) push(node Node) { n.Nodes = append(n.Nodes, node) }
func (n *nodeStack) pop() Node {
var r Node
if len(n.Nodes) > 0 {
r = n.Nodes[len(n.Nodes)-1]
n.Nodes = n.Nodes[:len(n.Nodes)-1]
}
return r
}

// ListNode holds a sequence of nodes.
type ListNode struct {
NodeType
Expand Down Expand Up @@ -156,3 +182,23 @@ func newLiteral(pos Pos, typ itemType, val string) Node {
}
panic(fmt.Sprint("unexpected literal type ", typ))
}

type AddExpr struct {
NodeType
Pos
lhs Node
rhs Node
operator item
}

func newAddExpr(lhs, rhs Node, operator item) *AddExpr {
return &AddExpr{NodeAdd, lhs.Position(), lhs, rhs, operator}
}

func (a *AddExpr) String() string {
return fmt.Sprintf("%s %s %s", a.lhs, a.operator.val, a.rhs)
}

func (a *AddExpr) Copy() Node {
return newAddExpr(a.lhs, a.rhs, a.operator)
}
51 changes: 51 additions & 0 deletions neo/ast_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package jigo

import (
"fmt"
"testing"
)

func TestStack(t *testing.T) {
var p Pos
var n Node
s := newStack(p)
s.push(n)
if s.len() != 1 {
t.Errorf("Expected s.len() to be 1, got %d\n", s.len())
}
s.pop()
if s.len() != 0 {
t.Errorf("Expected s.len() to be 0, got %d\n", s.len())
}
n = s.pop()
if n != nil {
t.Errorf("Expected n to be nil, but was %v\n", n)
}
s.push(newList(p))
s.push(newLookup(p, "foo"))
s.push(newText(p, "Hello!"))

if s.len() != 3 {
t.Errorf("Expected s.len() to be 3, got %d\n", s.len())
}
n = s.pop()
if n.Type() != NodeText {
t.Errorf("Expected n.Type to be NodeText, got %s\n", n.Type())
}
if n.String() != "Hello!" {
t.Errorf("Expected n.String() to be \"Hello!\", got %s\n", n.String())
}

n = s.pop()

if n.Type() != NodeLookup {
t.Errorf("Expected n.Type() to be NodeLookup, got %s\n", n.Type())
}
if n.String() != "foo" {
t.Errorf("Expected n.String() to be \"foo\", got %s\n", n.String())
}
if s.len() != 1 {
t.Errorf("Expected len of 1, got %d\n", s.len())
}
fmt.Println(s)
}
28 changes: 20 additions & 8 deletions neo/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ type Tree struct {
// described to know if 3 is sufficient.
token [3]item // three-token lookahead for parser.
peekCount int
stack nodeStack
// vars []string // variables defined at the moment.
}

Expand Down Expand Up @@ -394,25 +395,36 @@ func (t *Tree) parseVar() Node {
// themselves.
func (t *Tree) parseExpr(terminator itemType) Node {
token := t.peekNonSpace()
expr := newList(token.pos)
stack := newStack(token.pos)
for {
token = t.peekNonSpace()
switch token.typ {
case terminator:
return expr
if stack.len() != 1 {
t.unexpected(token, "zero length expression")
}
return stack.pop()
case tokenName:
expr.append(t.lookupExpr())
stack.push(t.lookupExpr())
case tokenLparen:
t.expect(tokenLparen)
expr.append(t.parseExpr(tokenRparen))
stack.push(t.parseExpr(tokenRparen))
case tokenLbrace:
expr.append(t.mapExpr())
stack.push(t.mapExpr())
case tokenLbracket:
expr.append(t.listExpr())
stack.push(t.listExpr())
case tokenFloat, tokenInteger, tokenString:
expr.append(t.literalExpr())
stack.push(t.literalExpr())
case tokenAdd, tokenSub:
t.next()
t.nextNonSpace()
if stack.len() > 0 {
lhs := stack.pop()
rhs := t.parseExpr(terminator)
// TODO: we must peek to see if the next oper is a mul oper
// in order to conserve order of operations
stack.push(newAddExpr(lhs, rhs, token))
}
// FIXME: unary + is a noop, but unary - isn't..
case tokenMul, tokenMod, tokenDiv, tokenFloordiv:
t.next()
default:
Expand Down

0 comments on commit 7510939

Please sign in to comment.