aboutsummaryrefslogtreecommitdiff
path: root/driver/parser_test.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2022-03-30 00:44:17 +0900
committerRyo Nihei <nihei.dev@gmail.com>2022-03-30 00:50:06 +0900
commita1e4ae763cbf824f0d32a706cfe0d9603ce99b02 (patch)
treee32f48d6d5d3f56d495a8684653e913f14ca5ec8 /driver/parser_test.go
parentMove directives given to lexical productions (diff)
downloadurubu-a1e4ae763cbf824f0d32a706cfe0d9603ce99b02.tar.gz
urubu-a1e4ae763cbf824f0d32a706cfe0d9603ce99b02.tar.xz
Allow an alternative to have multiple directives
Diffstat (limited to 'driver/parser_test.go')
-rw-r--r--driver/parser_test.go118
1 files changed, 116 insertions, 2 deletions
diff --git a/driver/parser_test.go b/driver/parser_test.go
index 9d89efa..d964cbc 100644
--- a/driver/parser_test.go
+++ b/driver/parser_test.go
@@ -252,7 +252,104 @@ foo #skip
src: `foo`,
specErr: true,
},
- // A lexical production cannot have alternative productions.
+ // A production cannot have production directives.
+ {
+ specSrc: `
+%name test
+
+s #prec foo
+ : foo
+ ;
+
+foo: 'foo' #skip;
+`,
+ src: `foo`,
+ specErr: true,
+ },
+ // A production can have multiple alternative productions.
+ {
+ specSrc: `
+%name test
+
+%left mul div
+%left add sub
+
+expr
+ : expr add expr
+ | expr sub expr
+ | expr mul expr
+ | expr div expr
+ | int
+ | sub int #prec mul #ast int sub // This 'sub' means the unary minus symbol.
+ ;
+
+int
+ : "0|[1-9][0-9]*";
+add
+ : '+';
+sub
+ : '-';
+mul
+ : '*';
+div
+ : '/';
+`,
+ src: `-1*-2+3-4/5`,
+ ast: nonTermNode("expr",
+ nonTermNode("expr",
+ nonTermNode("expr",
+ nonTermNode("expr",
+ termNode("int", "1"),
+ termNode("sub", "-"),
+ ),
+ termNode("mul", "*"),
+ nonTermNode("expr",
+ termNode("int", "2"),
+ termNode("sub", "-"),
+ ),
+ ),
+ termNode("add", "+"),
+ nonTermNode("expr",
+ termNode("int", "3"),
+ ),
+ ),
+ termNode("sub", "-"),
+ nonTermNode("expr",
+ nonTermNode("expr",
+ termNode("int", "4"),
+ ),
+ termNode("div", "/"),
+ nonTermNode("expr",
+ termNode("int", "5"),
+ ),
+ ),
+ ),
+ },
+ // A lexical production can have multiple production directives.
+ {
+ specSrc: `
+%name test
+
+s
+ : push_a push_b pop pop
+ ;
+
+push_a #mode default #push a
+ : '->a';
+push_b #mode a #push b
+ : '->b';
+pop #mode a b #pop
+ : '<-';
+`,
+ src: `->a->b<-<-`,
+ ast: nonTermNode("s",
+ termNode("push_a", "->a"),
+ termNode("push_b", "->b"),
+ termNode("pop", "<-"),
+ termNode("pop", "<-"),
+ ),
+ },
+ // A lexical production cannot have alternative directives.
{
specSrc: `
%name test
@@ -266,7 +363,7 @@ foo: 'foo' #skip;
src: `foo`,
specErr: true,
},
- // A directive must not be duplicated.
+ // A production directive must not be duplicated.
{
specSrc: `
%name test
@@ -281,6 +378,23 @@ foo #skip #skip
src: `foo`,
specErr: true,
},
+ // An alternative directive must not be duplicated.
+ {
+ specSrc: `
+%name test
+
+s
+ : foo bar #ast foo bar #ast foo bar
+ ;
+
+foo
+ : 'foo';
+bar
+ : 'bar';
+`,
+ src: `foobar`,
+ specErr: true,
+ },
{
specSrc: `
%name test