aboutsummaryrefslogtreecommitdiff
path: root/spec/parser_test.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2022-05-07 20:41:33 +0900
committerRyo Nihei <nihei.dev@gmail.com>2022-05-10 23:14:41 +0900
commit3eb0e88f911386a4e6eca991c1471070596c5554 (patch)
tree4c3ea445a804d781b846739d70392ceb1353ea6d /spec/parser_test.go
parentMake #prec directive change only precedence and not associativity (diff)
downloadurubu-3eb0e88f911386a4e6eca991c1471070596c5554.tar.gz
urubu-3eb0e88f911386a4e6eca991c1471070596c5554.tar.xz
Change syntax for top-level directives
%name changes to: #name example; %left and %right change to: #prec ( #left a b #right c d );
Diffstat (limited to 'spec/parser_test.go')
-rw-r--r--spec/parser_test.go169
1 files changed, 138 insertions, 31 deletions
diff --git a/spec/parser_test.go b/spec/parser_test.go
index 2a44acd..de2c6f7 100644
--- a/spec/parser_test.go
+++ b/spec/parser_test.go
@@ -8,6 +8,20 @@ import (
)
func TestParse(t *testing.T) {
+ name := func(param *ParameterNode) *DirectiveNode {
+ return &DirectiveNode{
+ Name: "name",
+ Parameters: []*ParameterNode{param},
+ }
+ }
+
+ prec := func(param *ParameterNode) *DirectiveNode {
+ return &DirectiveNode{
+ Name: "prec",
+ Parameters: []*ParameterNode{param},
+ }
+ }
+
leftAssoc := func(params ...*ParameterNode) *DirectiveNode {
return &DirectiveNode{
Name: "left",
@@ -66,6 +80,11 @@ func TestParse(t *testing.T) {
param.Expansion = true
return param
}
+ group := func(dirs ...*DirectiveNode) *ParameterNode {
+ return &ParameterNode{
+ Group: dirs,
+ }
+ }
withParamPos := func(param *ParameterNode, pos Position) *ParameterNode {
param.Pos = pos
return param
@@ -122,6 +141,82 @@ func TestParse(t *testing.T) {
synErr *SyntaxError
}{
{
+ caption: "a grammar can contain top-level directives",
+ src: `
+#name test;
+
+#prec (
+ #left a b
+ #right c d
+);
+`,
+ ast: &RootNode{
+ Directives: []*DirectiveNode{
+ withDirPos(
+ name(
+ withParamPos(
+ idParam("test"),
+ newPos(2),
+ ),
+ ),
+ newPos(2),
+ ),
+ withDirPos(
+ prec(
+ withParamPos(
+ group(
+ withDirPos(
+ leftAssoc(
+ withParamPos(
+ idParam("a"),
+ newPos(5),
+ ),
+ withParamPos(
+ idParam("b"),
+ newPos(5),
+ ),
+ ),
+ newPos(5),
+ ),
+ withDirPos(
+ rightAssoc(
+ withParamPos(
+ idParam("c"),
+ newPos(6),
+ ),
+ withParamPos(
+ idParam("d"),
+ newPos(6),
+ ),
+ ),
+ newPos(6),
+ ),
+ ),
+ newPos(4),
+ ),
+ ),
+ newPos(4),
+ ),
+ },
+ },
+ },
+ {
+ caption: "a top-level directive must be followed by ';'",
+ src: `
+#name test
+`,
+ synErr: synErrTopLevelDirNoSemicolon,
+ },
+ {
+ caption: "a directive group must be closed by ')'",
+ src: `
+#prec (
+ #left a b
+;
+`,
+ synErr: synErrUnclosedDirGroup,
+ },
+ {
caption: "single production is a valid grammar",
src: `a: "a";`,
ast: &RootNode{
@@ -643,10 +738,12 @@ foo
{
caption: "a grammar can contain left and right associativities",
src: `
-%left l1 l2
-%left l3
-%right r1 r2
-%right r3
+#prec (
+ #left l1 l2
+ #left l3
+ #right r1 r2
+ #right r3
+);
s
: id l1 id l2 id l3 id
@@ -671,33 +768,43 @@ id
: "[A-Za-z0-9_]+";
`,
ast: &RootNode{
- MetaData: []*DirectiveNode{
+ Directives: []*DirectiveNode{
withDirPos(
- leftAssoc(
- withParamPos(idParam("l1"), newPos(2)),
- withParamPos(idParam("l2"), newPos(2)),
+ prec(
+ withParamPos(
+ group(
+ withDirPos(
+ leftAssoc(
+ withParamPos(idParam("l1"), newPos(3)),
+ withParamPos(idParam("l2"), newPos(3)),
+ ),
+ newPos(3),
+ ),
+ withDirPos(
+ leftAssoc(
+ withParamPos(idParam("l3"), newPos(4)),
+ ),
+ newPos(4),
+ ),
+ withDirPos(
+ rightAssoc(
+ withParamPos(idParam("r1"), newPos(5)),
+ withParamPos(idParam("r2"), newPos(5)),
+ ),
+ newPos(5),
+ ),
+ withDirPos(
+ rightAssoc(
+ withParamPos(idParam("r3"), newPos(6)),
+ ),
+ newPos(6),
+ ),
+ ),
+ newPos(2),
+ ),
),
newPos(2),
),
- withDirPos(
- leftAssoc(
- withParamPos(idParam("l3"), newPos(3)),
- ),
- newPos(3),
- ),
- withDirPos(
- rightAssoc(
- withParamPos(idParam("r1"), newPos(4)),
- withParamPos(idParam("r2"), newPos(4)),
- ),
- newPos(4),
- ),
- withDirPos(
- rightAssoc(
- withParamPos(idParam("r3"), newPos(5)),
- ),
- newPos(5),
- ),
},
Productions: []*ProductionNode{
prod("s",
@@ -756,11 +863,11 @@ func testRootNode(t *testing.T, root, expected *RootNode, checkPosition bool) {
if len(root.Productions) != len(expected.Productions) {
t.Fatalf("unexpected length of productions; want: %v, got: %v", len(expected.Productions), len(root.Productions))
}
- if len(root.MetaData) != len(expected.MetaData) {
- t.Fatalf("unexpected length of meta data; want: %v, got: %v", len(expected.MetaData), len(root.MetaData))
+ if len(root.Directives) != len(expected.Directives) {
+ t.Fatalf("unexpected length of top-level directives; want: %v, got: %v", len(expected.Directives), len(root.Directives))
}
- for i, md := range root.MetaData {
- testDirectives(t, []*DirectiveNode{md}, []*DirectiveNode{expected.MetaData[i]}, true)
+ for i, dir := range root.Directives {
+ testDirectives(t, []*DirectiveNode{dir}, []*DirectiveNode{expected.Directives[i]}, true)
}
for i, prod := range root.Productions {
testProductionNode(t, prod, expected.Productions[i], checkPosition)