aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2022-03-29 19:10:23 +0900
committerRyo Nihei <nihei.dev@gmail.com>2022-03-29 19:10:23 +0900
commitdbd2e20de97cdef56da0de07adff4251de94ef43 (patch)
tree0f21929ff0147d757c59e6ac558f0c68fc100846
parentUse IDs and labels as parameters of an #ast directive instead of symbol posit... (diff)
downloadurubu-dbd2e20de97cdef56da0de07adff4251de94ef43.tar.gz
urubu-dbd2e20de97cdef56da0de07adff4251de94ef43.tar.xz
Change syntax of production directives
The position of directives given to productions has moved from before a left-hand side value to after a left-hand side value. This change aims to simplify the syntax. However, there is no change in positions of directives given to alternatives.
-rw-r--r--driver/parser_test.go28
-rw-r--r--spec/parser.go9
-rw-r--r--spec/parser_test.go95
-rw-r--r--spec/syntax_error.go1
4 files changed, 57 insertions, 76 deletions
diff --git a/driver/parser_test.go b/driver/parser_test.go
index 050e51a..9a3e040 100644
--- a/driver/parser_test.go
+++ b/driver/parser_test.go
@@ -264,15 +264,17 @@ mode_tran
| pop_m1
| pop_m2
;
-push_m1: "->" #push m1;
-#mode m1
-push_m2: "-->" #push m2;
-#mode m1
-pop_m1 : "<-" #pop;
-#mode m2
-pop_m2: "<--" #pop;
-#mode default m1 m2
-whitespace: "\u{0020}+" #skip;
+
+push_m1
+ : "->" #push m1;
+push_m2 #mode m1
+ : "-->" #push m2;
+pop_m1 #mode m1
+ : "<-" #pop;
+pop_m2 #mode m2
+ : "<--" #pop;
+whitespace #mode default m1 m2
+ : "\u{0020}+" #skip;
`,
src: ` -> --> <-- <- `,
},
@@ -283,9 +285,11 @@ whitespace: "\u{0020}+" #skip;
s
: foo bar
;
-foo: "foo";
-#mode default
-bar: "bar";
+
+foo
+ : "foo";
+bar #mode default
+ : "bar";
`,
src: `foobar`,
},
diff --git a/spec/parser.go b/spec/parser.go
index e092f59..be20e7d 100644
--- a/spec/parser.go
+++ b/spec/parser.go
@@ -306,19 +306,14 @@ func (p *parser) parseProduction() *ProductionNode {
return nil
}
- dir := p.parseDirective()
- if dir != nil {
- if !p.consume(tokenKindNewline) {
- raiseSyntaxError(p.pos.Row, synErrProdDirNoNewline)
- }
- }
-
if !p.consume(tokenKindID) {
raiseSyntaxError(p.pos.Row, synErrNoProductionName)
}
lhs := p.lastTok.text
lhsPos := p.lastTok.pos
+ dir := p.parseDirective()
+
p.consume(tokenKindNewline)
if !p.consume(tokenKindColon) {
diff --git a/spec/parser_test.go b/spec/parser_test.go
index 3cc772d..24e9468 100644
--- a/spec/parser_test.go
+++ b/spec/parser_test.go
@@ -298,15 +298,17 @@ mode_tran
| pop_m1
| pop_m2
;
-push_m1: "->" #push m1;
-#mode m1
-push_m2: "-->" #push m2;
-#mode m1
-pop_m1 : "<-" #pop;
-#mode m2
-pop_m2: "<--" #pop;
-#mode default m1 m2
-whitespace: "\u{0020}+" #skip;
+
+push_m1
+ : "->" #push m1;
+push_m2 #mode m1
+ : "-->" #push m2;
+pop_m1 #mode m1
+ : "<-" #pop;
+pop_m2 #mode m2
+ : "<--" #pop;
+whitespace #mode default m1 m2
+ : "\u{0020}+" #skip;
`,
ast: &RootNode{
Productions: []*ProductionNode{
@@ -368,13 +370,6 @@ whitespace: "\u{0020}+" #skip;
},
},
{
- caption: "a production directive must be followed by a newline",
- src: `
-#mode foo;
-`,
- synErr: synErrProdDirNoNewline,
- },
- {
caption: "a production must be followed by a newline",
src: `
s: foo; foo: "foo";
@@ -426,7 +421,6 @@ bar: "bar";
{
caption: "an AST has node positions",
src: `
-#mode default
exp
: exp "\+" id #ast exp id
| id
@@ -440,43 +434,32 @@ fragment number: "[0-9]";
ast: &RootNode{
Productions: []*ProductionNode{
withProdPos(
- withProdDir(
- prod("exp",
- withAltPos(
- withAltDir(
- alt(
- withElemPos(id("exp"), newPos(4)),
- withElemPos(pat(`\+`), newPos(4)),
- withElemPos(id("id"), newPos(4)),
- ),
- withDirPos(
- dir("ast",
- withParamPos(idParam("exp"), newPos(4)),
- withParamPos(idParam("id"), newPos(4)),
- ),
- newPos(4),
- ),
- ),
- newPos(4),
- ),
- withAltPos(
+ prod("exp",
+ withAltPos(
+ withAltDir(
alt(
- withElemPos(id("id"), newPos(5)),
+ withElemPos(id("exp"), newPos(3)),
+ withElemPos(pat(`\+`), newPos(3)),
+ withElemPos(id("id"), newPos(3)),
+ ),
+ withDirPos(
+ dir("ast",
+ withParamPos(idParam("exp"), newPos(3)),
+ withParamPos(idParam("id"), newPos(3)),
+ ),
+ newPos(3),
),
- newPos(5),
),
+ newPos(3),
),
- withDirPos(
- dir("mode",
- withParamPos(
- idParam("default"),
- newPos(2),
- ),
+ withAltPos(
+ alt(
+ withElemPos(id("id"), newPos(4)),
),
- newPos(2),
+ newPos(4),
),
),
- newPos(3),
+ newPos(2),
),
},
LexProductions: []*ProductionNode{
@@ -487,18 +470,18 @@ fragment number: "[0-9]";
alt(
withElemPos(
pat(`\u{0020}+`),
- newPos(7),
+ newPos(6),
),
),
withDirPos(
dir("skip"),
- newPos(7),
+ newPos(6),
),
),
- newPos(7),
+ newPos(6),
),
),
- newPos(7),
+ newPos(6),
),
withProdPos(
prod("id",
@@ -506,23 +489,23 @@ fragment number: "[0-9]";
alt(
withElemPos(
pat(`\f{letter}(\f{letter}|\f{number})*`),
- newPos(8),
+ newPos(7),
),
),
- newPos(8),
+ newPos(7),
),
),
- newPos(8),
+ newPos(7),
),
},
Fragments: []*FragmentNode{
withFragmentPos(
frag("letter", "[A-Za-z_]"),
- newPos(9),
+ newPos(8),
),
withFragmentPos(
frag("number", "[0-9]"),
- newPos(10),
+ newPos(9),
),
},
},
diff --git a/spec/syntax_error.go b/spec/syntax_error.go
index 92348db..c4e6594 100644
--- a/spec/syntax_error.go
+++ b/spec/syntax_error.go
@@ -31,7 +31,6 @@ var (
synErrLabelWithNoSymbol = newSyntaxError("a label must follow a symbol")
synErrNoLabel = newSyntaxError("an identifier that represents a label is missing after the label marker @")
synErrNoDirectiveName = newSyntaxError("a directive needs a name")
- synErrProdDirNoNewline = newSyntaxError("a production directive must be followed by a newline")
synErrSemicolonNoNewline = newSyntaxError("a semicolon must be followed by a newline")
synErrFragmentNoPattern = newSyntaxError("a fragment needs one pattern element")
)