aboutsummaryrefslogtreecommitdiff
path: root/spec/parser.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-06-30 23:44:50 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-06-30 23:54:01 +0900
commitb8b71860d7df5d06dd8a2b9ac62035e8ba8778a7 (patch)
treec0075cd6813085401dbaf44e62ca14ec2b93d30c /spec/parser.go
parentAdd testing for the driver (diff)
downloadcotia-b8b71860d7df5d06dd8a2b9ac62035e8ba8778a7.tar.gz
cotia-b8b71860d7df5d06dd8a2b9ac62035e8ba8778a7.tar.xz
Simplify syntax of modifiers and semantic actions
Modifiers and semantic actions are represented by directives following the '#' symbol.
Diffstat (limited to 'spec/parser.go')
-rw-r--r--spec/parser.go82
1 files changed, 46 insertions, 36 deletions
diff --git a/spec/parser.go b/spec/parser.go
index 6f5e13f..8322a3f 100644
--- a/spec/parser.go
+++ b/spec/parser.go
@@ -10,19 +10,14 @@ type RootNode struct {
}
type ProductionNode struct {
- Modifier *ModifierNode
- LHS string
- RHS []*AlternativeNode
-}
-
-type ModifierNode struct {
- Name string
- Parameter string
+ Directive *DirectiveNode
+ LHS string
+ RHS []*AlternativeNode
}
type AlternativeNode struct {
- Elements []*ElementNode
- Action *ActionNode
+ Elements []*ElementNode
+ Directive *DirectiveNode
}
type ElementNode struct {
@@ -30,7 +25,7 @@ type ElementNode struct {
Pattern string
}
-type ActionNode struct {
+type DirectiveNode struct {
Name string
Parameter *ParameterNode
}
@@ -102,6 +97,8 @@ func (p *parser) parseRoot() *RootNode {
var prods []*ProductionNode
var fragments []*FragmentNode
for {
+ p.consume(tokenKindNewline)
+
fragment := p.parseFragment()
if fragment != nil {
fragments = append(fragments, fragment)
@@ -131,11 +128,15 @@ func (p *parser) parseFragment() *FragmentNode {
return nil
}
+ p.consume(tokenKindNewline)
+
if !p.consume(tokenKindID) {
raiseSyntaxError(synErrNoProductionName)
}
lhs := p.lastTok.text
+ p.consume(tokenKindNewline)
+
if !p.consume(tokenKindColon) {
raiseSyntaxError(synErrNoColon)
}
@@ -145,10 +146,18 @@ func (p *parser) parseFragment() *FragmentNode {
}
rhs := p.lastTok.text
+ p.consume(tokenKindNewline)
+
if !p.consume(tokenKindSemicolon) {
raiseSyntaxError(synErrNoSemicolon)
}
+ if !p.consume(tokenKindNewline) {
+ if !p.consume(tokenKindEOF) {
+ raiseSyntaxError(synErrSemicolonNoNewline)
+ }
+ }
+
return &FragmentNode{
LHS: lhs,
RHS: rhs,
@@ -160,21 +169,10 @@ func (p *parser) parseProduction() *ProductionNode {
return nil
}
- var mod *ModifierNode
- if p.consume(tokenKindModifierMarker) {
- if !p.consume(tokenKindID) {
- raiseSyntaxError(synErrNoModifierName)
- }
- name := p.lastTok.text
-
- var param string
- if p.consume(tokenKindID) {
- param = p.lastTok.text
- }
-
- mod = &ModifierNode{
- Name: name,
- Parameter: param,
+ dir := p.parseDirective()
+ if dir != nil {
+ if !p.consume(tokenKindNewline) {
+ raiseSyntaxError(synErrProdDirNoNewline)
}
}
@@ -183,6 +181,8 @@ func (p *parser) parseProduction() *ProductionNode {
}
lhs := p.lastTok.text
+ p.consume(tokenKindNewline)
+
if !p.consume(tokenKindColon) {
raiseSyntaxError(synErrNoColon)
}
@@ -190,6 +190,8 @@ func (p *parser) parseProduction() *ProductionNode {
alt := p.parseAlternative()
rhs := []*AlternativeNode{alt}
for {
+ p.consume(tokenKindNewline)
+
if !p.consume(tokenKindOr) {
break
}
@@ -197,14 +199,22 @@ func (p *parser) parseProduction() *ProductionNode {
rhs = append(rhs, alt)
}
+ p.consume(tokenKindNewline)
+
if !p.consume(tokenKindSemicolon) {
raiseSyntaxError(synErrNoSemicolon)
}
+ if !p.consume(tokenKindNewline) {
+ if !p.consume(tokenKindEOF) {
+ raiseSyntaxError(synErrSemicolonNoNewline)
+ }
+ }
+
return &ProductionNode{
- Modifier: mod,
- LHS: lhs,
- RHS: rhs,
+ Directive: dir,
+ LHS: lhs,
+ RHS: rhs,
}
}
@@ -218,11 +228,11 @@ func (p *parser) parseAlternative() *AlternativeNode {
elems = append(elems, elem)
}
- act := p.parseAction()
+ dir := p.parseDirective()
return &AlternativeNode{
- Elements: elems,
- Action: act,
+ Elements: elems,
+ Directive: dir,
}
}
@@ -240,13 +250,13 @@ func (p *parser) parseElement() *ElementNode {
return nil
}
-func (p *parser) parseAction() *ActionNode {
- if !p.consume(tokenKindActionLeader) {
+func (p *parser) parseDirective() *DirectiveNode {
+ if !p.consume(tokenKindDirectiveMarker) {
return nil
}
if !p.consume(tokenKindID) {
- raiseSyntaxError(synErrNoActionName)
+ raiseSyntaxError(synErrNoDirectiveName)
}
name := p.lastTok.text
@@ -290,7 +300,7 @@ func (p *parser) parseAction() *ActionNode {
}
}
- return &ActionNode{
+ return &DirectiveNode{
Name: name,
Parameter: param,
}