diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-06-15 19:44:51 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-06-15 19:44:51 +0900 |
commit | 434ee1561016d0fd5099c755b150365b7a528c6b (patch) | |
tree | 682b822a8b30df0bcab5e132068232dce88360a4 /spec/parser.go | |
parent | Add spec parser (diff) | |
download | cotia-434ee1561016d0fd5099c755b150365b7a528c6b.tar.gz cotia-434ee1561016d0fd5099c755b150365b7a528c6b.tar.xz |
Add production syntax
Diffstat (limited to 'spec/parser.go')
-rw-r--r-- | spec/parser.go | 38 |
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 { |