aboutsummaryrefslogtreecommitdiff
path: root/spec/parser.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-06-15 19:44:51 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-06-15 19:44:51 +0900
commit434ee1561016d0fd5099c755b150365b7a528c6b (patch)
tree682b822a8b30df0bcab5e132068232dce88360a4 /spec/parser.go
parentAdd spec parser (diff)
downloadcotia-434ee1561016d0fd5099c755b150365b7a528c6b.tar.gz
cotia-434ee1561016d0fd5099c755b150365b7a528c6b.tar.xz
Add production syntax
Diffstat (limited to 'spec/parser.go')
-rw-r--r--spec/parser.go38
1 files changed, 28 insertions, 10 deletions
diff --git a/spec/parser.go b/spec/parser.go
index a204cb7..3e86779 100644
--- a/spec/parser.go
+++ b/spec/parser.go
@@ -18,6 +18,7 @@ type AlternativeNode struct {
}
type ElementNode struct {
+ ID string
Pattern string
}
@@ -94,32 +95,49 @@ func (p *parser) parseProduction() *ProductionNode {
raiseSyntaxError(synErrNoColon)
}
alt := p.parseAlternative()
+ rhs := []*AlternativeNode{alt}
+ for {
+ if !p.consume(tokenKindOr) {
+ break
+ }
+ alt := p.parseAlternative()
+ rhs = append(rhs, alt)
+ }
if !p.consume(tokenKindSemicolon) {
raiseSyntaxError(synErrNoSemicolon)
}
return &ProductionNode{
LHS: lhs,
- RHS: []*AlternativeNode{alt},
+ RHS: rhs,
}
}
func (p *parser) parseAlternative() *AlternativeNode {
- elem := p.parseElement()
- if elem == nil {
- raiseSyntaxError(synErrNoElement)
+ elems := []*ElementNode{}
+ for {
+ elem := p.parseElement()
+ if elem == nil {
+ break
+ }
+ elems = append(elems, elem)
}
return &AlternativeNode{
- Elements: []*ElementNode{elem},
+ Elements: elems,
}
}
func (p *parser) parseElement() *ElementNode {
- if !p.consume(tokenKindTerminalPattern) {
- return nil
- }
- return &ElementNode{
- Pattern: p.lastTok.text,
+ switch {
+ case p.consume(tokenKindID):
+ return &ElementNode{
+ ID: p.lastTok.text,
+ }
+ case p.consume(tokenKindTerminalPattern):
+ return &ElementNode{
+ Pattern: p.lastTok.text,
+ }
}
+ return nil
}
func (p *parser) consume(expected tokenKind) bool {