diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-06-20 18:39:38 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-06-20 18:46:13 +0900 |
commit | 8993406a8ebe8c0a01d5081dc4afcf819e3160d4 (patch) | |
tree | 8940654c0bbc1e200908cafe83813fe7765a5229 /spec/parser.go | |
parent | Add syntax of comments (diff) | |
download | cotia-8993406a8ebe8c0a01d5081dc4afcf819e3160d4.tar.gz cotia-8993406a8ebe8c0a01d5081dc4afcf819e3160d4.tar.xz |
Add syntax of modifiers and actions
Currently, a mode modifier and push/pop actions are available.
The modifier and the actions make sense in only lexical specifications.
Diffstat (limited to 'spec/parser.go')
-rw-r--r-- | spec/parser.go | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/spec/parser.go b/spec/parser.go index 3e86779..1654752 100644 --- a/spec/parser.go +++ b/spec/parser.go @@ -9,12 +9,19 @@ type RootNode struct { } type ProductionNode struct { - LHS string - RHS []*AlternativeNode + Modifier *ModifierNode + LHS string + RHS []*AlternativeNode +} + +type ModifierNode struct { + Name string + Parameter string } type AlternativeNode struct { Elements []*ElementNode + Action *ActionNode } type ElementNode struct { @@ -22,6 +29,11 @@ type ElementNode struct { Pattern string } +type ActionNode struct { + Name string + Parameter string +} + func raiseSyntaxError(synErr *SyntaxError) { panic(synErr) } @@ -87,13 +99,34 @@ func (p *parser) parseProduction() *ProductionNode { if p.consume(tokenKindEOF) { 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, + } + } + if !p.consume(tokenKindID) { raiseSyntaxError(synErrNoProductionName) } lhs := p.lastTok.text + if !p.consume(tokenKindColon) { raiseSyntaxError(synErrNoColon) } + alt := p.parseAlternative() rhs := []*AlternativeNode{alt} for { @@ -103,12 +136,15 @@ func (p *parser) parseProduction() *ProductionNode { alt := p.parseAlternative() rhs = append(rhs, alt) } + if !p.consume(tokenKindSemicolon) { raiseSyntaxError(synErrNoSemicolon) } + return &ProductionNode{ - LHS: lhs, - RHS: rhs, + Modifier: mod, + LHS: lhs, + RHS: rhs, } } @@ -121,8 +157,28 @@ func (p *parser) parseAlternative() *AlternativeNode { } elems = append(elems, elem) } + + var act *ActionNode + if p.consume(tokenKindActionLeader) { + if !p.consume(tokenKindID) { + raiseSyntaxError(synErrNoActionName) + } + name := p.lastTok.text + + var param string + if p.consume(tokenKindID) { + param = p.lastTok.text + } + + act = &ActionNode{ + Name: name, + Parameter: param, + } + } + return &AlternativeNode{ Elements: elems, + Action: act, } } |