From 434ee1561016d0fd5099c755b150365b7a528c6b Mon Sep 17 00:00:00 2001 From: Ryo Nihei Date: Tue, 15 Jun 2021 19:44:51 +0900 Subject: Add production syntax --- spec/parser.go | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'spec/parser.go') 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 { -- cgit v1.2.3