aboutsummaryrefslogtreecommitdiff
path: root/spec/parser.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-08-22 15:39:27 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-08-22 15:44:03 +0900
commit4d879b95d5368d578a39baaefba0de743a764105 (patch)
treea0e78f5c9916405545f1e7b139f9427b1cd190cc /spec/parser.go
parentResolve conflicts by default rules (diff)
downloadcotia-4d879b95d5368d578a39baaefba0de743a764105.tar.gz
cotia-4d879b95d5368d578a39baaefba0de743a764105.tar.xz
Support %left and %right to specify precedences and associativities
Diffstat (limited to 'spec/parser.go')
-rw-r--r--spec/parser.go57
1 files changed, 57 insertions, 0 deletions
diff --git a/spec/parser.go b/spec/parser.go
index 29248f4..53bf491 100644
--- a/spec/parser.go
+++ b/spec/parser.go
@@ -8,6 +8,7 @@ import (
)
type RootNode struct {
+ MetaData []*DirectiveNode
Productions []*ProductionNode
LexProductions []*ProductionNode
Fragments []*FragmentNode
@@ -135,10 +136,17 @@ func (p *parser) parseRoot() *RootNode {
}
}()
+ var metadata []*DirectiveNode
var prods []*ProductionNode
var lexProds []*ProductionNode
var fragments []*FragmentNode
for {
+ md := p.parseMetaData()
+ if md != nil {
+ metadata = append(metadata, md)
+ continue
+ }
+
fragment := p.parseFragment()
if fragment != nil {
fragments = append(fragments, fragment)
@@ -161,12 +169,61 @@ func (p *parser) parseRoot() *RootNode {
}
return &RootNode{
+ MetaData: metadata,
Productions: prods,
LexProductions: lexProds,
Fragments: fragments,
}
}
+func (p *parser) parseMetaData() *DirectiveNode {
+ defer func() {
+ err := recover()
+ if err == nil {
+ return
+ }
+
+ specErr, ok := err.(*verr.SpecError)
+ if !ok {
+ panic(err)
+ }
+
+ p.errs = append(p.errs, specErr)
+ p.skipOverTo(tokenKindNewline)
+
+ return
+ }()
+
+ p.consume(tokenKindNewline)
+
+ if !p.consume(tokenKindMetaDataMarker) {
+ return nil
+ }
+ mdPos := p.lastTok.pos
+
+ if !p.consume(tokenKindID) {
+ raiseSyntaxError(p.pos.Row, synErrNoProductionName)
+ }
+ name := p.lastTok.text
+
+ var params []*ParameterNode
+ for {
+ if !p.consume(tokenKindID) {
+ break
+ }
+ params = append(params, &ParameterNode{
+ ID: p.lastTok.text,
+ Pos: p.lastTok.pos,
+ })
+ }
+
+ return &DirectiveNode{
+ Name: name,
+ Parameters: params,
+ Pos: mdPos,
+ }
+}
+
func (p *parser) parseFragment() *FragmentNode {
defer func() {
err := recover()