Simplified calculator 2 example.
This commit is contained in:
parent
11883b06ac
commit
e1534f678e
|
@ -98,11 +98,11 @@ func (c *calculator) expr(p *parsekit.ParseAPI) {
|
|||
var pc, a = parsekit.C, parsekit.A
|
||||
if p.Handle(c.term) {
|
||||
for p.On(pc.Any(a.Add, a.Subtract)).Skip() {
|
||||
c.interpreter.pushOperator(p.LastMatch)
|
||||
op := p.LastMatch
|
||||
if !p.Handle(c.term) {
|
||||
return
|
||||
}
|
||||
c.interpreter.eval()
|
||||
c.interpreter.eval(op)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,11 +116,11 @@ func (c *calculator) term(p *parsekit.ParseAPI) {
|
|||
var pc, a = parsekit.C, parsekit.A
|
||||
if p.Handle(c.factor) {
|
||||
for p.On(pc.Any(a.Multiply, a.Divide)).Skip() {
|
||||
c.interpreter.pushOperator(p.LastMatch)
|
||||
op := p.LastMatch
|
||||
if !p.Handle(c.factor) {
|
||||
return
|
||||
}
|
||||
c.interpreter.eval()
|
||||
c.interpreter.eval(op)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,9 +164,8 @@ func (c *calculator) factor(p *parsekit.ParseAPI) {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
type stackFrame struct {
|
||||
a float64
|
||||
b float64
|
||||
op func(a, b float64) float64
|
||||
a float64
|
||||
b float64
|
||||
}
|
||||
|
||||
type interpreter struct {
|
||||
|
@ -175,51 +174,38 @@ type interpreter struct {
|
|||
result float64
|
||||
}
|
||||
|
||||
func (i *interpreter) push() *stackFrame {
|
||||
func (i *interpreter) push() {
|
||||
f := &stackFrame{}
|
||||
i.stack = append(i.stack, f)
|
||||
i.top = f
|
||||
i.pushOperator("VAL")
|
||||
return f
|
||||
i.top, i.stack = f, append(i.stack, f)
|
||||
}
|
||||
|
||||
func (i *interpreter) pop() float64 {
|
||||
value := i.eval()
|
||||
func (i *interpreter) pop() {
|
||||
popped := i.top
|
||||
i.stack = i.stack[0 : len(i.stack)-1]
|
||||
if len(i.stack) > 0 {
|
||||
i.top = i.stack[len(i.stack)-1]
|
||||
i.pushValue(value)
|
||||
i.pushValue(popped.b)
|
||||
} else {
|
||||
i.result = i.top.b
|
||||
i.top = nil
|
||||
i.result = popped.b
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (i *interpreter) pushValue(value float64) {
|
||||
i.top.a, i.top.b = i.top.b, value
|
||||
}
|
||||
|
||||
func (i *interpreter) pushOperator(op string) {
|
||||
func (i *interpreter) eval(op string) float64 {
|
||||
value := i.top.a
|
||||
switch op {
|
||||
case "VAL":
|
||||
i.top.op = func(a, b float64) float64 { return b }
|
||||
case "+":
|
||||
i.top.op = func(a, b float64) float64 { return a + b }
|
||||
value += i.top.b
|
||||
case "-":
|
||||
i.top.op = func(a, b float64) float64 { return a - b }
|
||||
value -= i.top.b
|
||||
case "*":
|
||||
i.top.op = func(a, b float64) float64 { return a * b }
|
||||
value *= i.top.b
|
||||
case "/":
|
||||
i.top.op = func(a, b float64) float64 { return a / b }
|
||||
default:
|
||||
panic(fmt.Sprintf("Unhandled op name: %s", op))
|
||||
value /= i.top.b
|
||||
}
|
||||
}
|
||||
|
||||
func (i *interpreter) eval() float64 {
|
||||
value := i.top.op(i.top.a, i.top.b)
|
||||
i.pushValue(value)
|
||||
i.pushOperator("VAL")
|
||||
i.top.b = value
|
||||
return value
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ func (p *ParseAPI) checkForLoops() {
|
|||
id := fmt.Sprintf("%s:%d", file, line)
|
||||
if _, ok := p.loopCheck[id]; ok {
|
||||
caller := runtime.FuncForPC(pc)
|
||||
panic(fmt.Sprintf("Loop detected in parser in %s at %s, line %d", caller.Name(), file, line))
|
||||
panic(fmt.Sprintf("Loop detected in parser in %s at %s", caller.Name(), id))
|
||||
}
|
||||
p.loopCheck[id] = true
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package parsekit_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.makaay.nl/mauricem/go-parsekit"
|
||||
|
@ -105,7 +104,7 @@ func TestGivenLoopingParserDefinition_ParserPanics(t *testing.T) {
|
|||
func() { parser.Execute("Het houdt niet op, niet vanzelf") },
|
||||
"Loop detected in parser in git.makaay.nl/mauricem/go-parsekit_test." +
|
||||
"(*parserWithLoop).second at /home/ubuntu/Projects/Parsekit/go-parsekit" +
|
||||
"/parsehandler_test.go, line 87"})
|
||||
"/parsehandler_test.go:87"})
|
||||
}
|
||||
|
||||
// This test incorporates an actual loop bug that I dropped on myself and
|
||||
|
@ -124,7 +123,6 @@ func TestGivenLoopingParserDefinition_ParserPanics(t *testing.T) {
|
|||
func TestGivenLoopingParserDefinition2_ParserPanics(t *testing.T) {
|
||||
parser := parsekit.NewParser(func(p *parsekit.ParseAPI) {
|
||||
for p.On(c.Max(5, a.AnyRune)).Accept() {
|
||||
fmt.Printf("Cycle: %s\n", p.BufLiteral())
|
||||
p.BufClear()
|
||||
}
|
||||
p.Stop()
|
||||
|
@ -133,5 +131,5 @@ func TestGivenLoopingParserDefinition2_ParserPanics(t *testing.T) {
|
|||
func() { parser.Execute("This will end soon") },
|
||||
"Loop detected in parser in git.makaay.nl/mauricem/go-parsekit_test." +
|
||||
"TestGivenLoopingParserDefinition2_ParserPanics.func1 at " +
|
||||
"/home/ubuntu/Projects/Parsekit/go-parsekit/parsehandler_test.go, line 126"})
|
||||
"/home/ubuntu/Projects/Parsekit/go-parsekit/parsehandler_test.go:125"})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue