diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2022-03-29 19:10:23 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2022-03-29 19:10:23 +0900 |
commit | dbd2e20de97cdef56da0de07adff4251de94ef43 (patch) | |
tree | 0f21929ff0147d757c59e6ac558f0c68fc100846 | |
parent | Use IDs and labels as parameters of an #ast directive instead of symbol posit... (diff) | |
download | urubu-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.go | 28 | ||||
-rw-r--r-- | spec/parser.go | 9 | ||||
-rw-r--r-- | spec/parser_test.go | 95 | ||||
-rw-r--r-- | spec/syntax_error.go | 1 |
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") ) |