goparsec
goparsec copied to clipboard
And(x, Maybe(And(y, z))) is broken
Consider this simplified grammar for addition:
Add ::= Int ("+" Int)?
Trying to express it with goparsec as follows:
package test
import (
"testing"
"github.com/prataprc/goparsec"
)
func TestParsec(t *testing.T) {
intP := goparsec.Int()
plusP := goparsec.Token("+", "op")
addP := goparsec.And(nil, intP, goparsec.Maybe(nil, goparsec.And(nil, plusP, intP)))
//addP := goparsec.OrdChoice(nil, goparsec.And(nil, intP, plusP, intP), intP) // (1)
//addP := goparsec.And(nil, intP, plusP, intP) // (2)
ast := goparsec.NewAST("expr", 32)
s := goparsec.NewScanner([]byte("1 + 2"))
_, err := ast.Parsewith(addP, s)
if err != nil {
t.Fatal(err)
}
}
Gives the following error:
=== RUN TestParsec
--- FAIL: TestParsec (0.00s)
panic: interface conversion: []parsec.ParsecNode is not parsec.Queryable: missing method GetAttribute [recovered]
panic: interface conversion: []parsec.ParsecNode is not parsec.Queryable: missing method GetAttribute
goroutine 6 [running]:
testing.tRunner.func1.1(0x52cb80, 0xc00007cdb0)
/nix/store/i14hzzs9ww364b5zl4c4g503rarwk09g-go-1.14.4/share/go/src/testing/testing.go:940 +0x2f5
testing.tRunner.func1(0xc000136120)
/nix/store/i14hzzs9ww364b5zl4c4g503rarwk09g-go-1.14.4/share/go/src/testing/testing.go:943 +0x3f9
panic(0x52cb80, 0xc00007cdb0)
/nix/store/i14hzzs9ww364b5zl4c4g503rarwk09g-go-1.14.4/share/go/src/runtime/panic.go:969 +0x166
PATH/vendor/github.com/prataprc/goparsec.(*AST).Parsewith(0xc00008df38, 0xc00007cb70, 0x583140, 0xc00007a230, 0xc00007cb70, 0x55, 0x37e, 0x4c0c30)
PATH/vendor/github.com/prataprc/goparsec/ast.go:90 +0xae
PATH/test.TestParsec(0xc000136120)
PATH/parser_test.go:19 +0x31e
testing.tRunner(0xc000136120, 0x55f4d0)
/nix/store/i14hzzs9ww364b5zl4c4g503rarwk09g-go-1.14.4/share/go/src/testing/testing.go:991 +0xdc
created by testing.(*T).Run
/nix/store/i14hzzs9ww364b5zl4c4g503rarwk09g-go-1.14.4/share/go/src/testing/testing.go:1042 +0x357
Process finished with exit code 1
Replacing the parser with (1) gives the same error, replacing with (2) works, but it is not equivalent (obviously).