aboutsummaryrefslogtreecommitdiff
path: root/spec/parser.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-06-20 23:47:29 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-06-20 23:47:29 +0900
commit8ab850528e1c05f36668f36db6af4cdcb647180e (patch)
treecf1e373ebd76c6ad78d65c79351b2198c7e42b2a /spec/parser.go
parentAdd skip action (diff)
downloadcotia-8ab850528e1c05f36668f36db6af4cdcb647180e.tar.gz
cotia-8ab850528e1c05f36668f36db6af4cdcb647180e.tar.xz
Add syntax of fragment
Diffstat (limited to 'spec/parser.go')
-rw-r--r--spec/parser.go67
1 files changed, 56 insertions, 11 deletions
diff --git a/spec/parser.go b/spec/parser.go
index 1654752..a2c41f8 100644
--- a/spec/parser.go
+++ b/spec/parser.go
@@ -6,6 +6,7 @@ import (
type RootNode struct {
Productions []*ProductionNode
+ Fragments []*FragmentNode
}
type ProductionNode struct {
@@ -34,6 +35,11 @@ type ActionNode struct {
Parameter string
}
+type FragmentNode struct {
+ LHS string
+ RHS string
+}
+
func raiseSyntaxError(synErr *SyntaxError) {
panic(synErr)
}
@@ -78,21 +84,60 @@ func (p *parser) parse() (root *RootNode, retErr error) {
}
func (p *parser) parseRoot() *RootNode {
- prod := p.parseProduction()
- if prod == nil {
- raiseSyntaxError(synErrNoProduction)
- }
- root := &RootNode{
- Productions: []*ProductionNode{prod},
- }
+ var prods []*ProductionNode
+ var fragments []*FragmentNode
for {
+ fragment := p.parseFragment()
+ if fragment != nil {
+ fragments = append(fragments, fragment)
+ continue
+ }
+
prod := p.parseProduction()
- if prod == nil {
- break
+ if prod != nil {
+ prods = append(prods, prod)
+ continue
}
- root.Productions = append(root.Productions, prod)
+
+ break
+ }
+ if len(prods) == 0 {
+ raiseSyntaxError(synErrNoProduction)
+ }
+
+ return &RootNode{
+ Productions: prods,
+ Fragments: fragments,
+ }
+}
+
+func (p *parser) parseFragment() *FragmentNode {
+ if !p.consume(tokenKindKWFragment) {
+ return nil
+ }
+
+ if !p.consume(tokenKindID) {
+ raiseSyntaxError(synErrNoProductionName)
+ }
+ lhs := p.lastTok.text
+
+ if !p.consume(tokenKindColon) {
+ raiseSyntaxError(synErrNoColon)
+ }
+
+ if !p.consume(tokenKindTerminalPattern) {
+ raiseSyntaxError(synErrFragmentNoPattern)
+ }
+ rhs := p.lastTok.text
+
+ if !p.consume(tokenKindSemicolon) {
+ raiseSyntaxError(synErrNoSemicolon)
+ }
+
+ return &FragmentNode{
+ LHS: lhs,
+ RHS: rhs,
}
- return root
}
func (p *parser) parseProduction() *ProductionNode {