From 8993406a8ebe8c0a01d5081dc4afcf819e3160d4 Mon Sep 17 00:00:00 2001 From: Ryo Nihei Date: Sun, 20 Jun 2021 18:39:38 +0900 Subject: Add syntax of modifiers and actions Currently, a mode modifier and push/pop actions are available. The modifier and the actions make sense in only lexical specifications. --- spec/parser.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) (limited to 'spec/parser.go') diff --git a/spec/parser.go b/spec/parser.go index 3e86779..1654752 100644 --- a/spec/parser.go +++ b/spec/parser.go @@ -9,12 +9,19 @@ type RootNode struct { } type ProductionNode struct { - LHS string - RHS []*AlternativeNode + Modifier *ModifierNode + LHS string + RHS []*AlternativeNode +} + +type ModifierNode struct { + Name string + Parameter string } type AlternativeNode struct { Elements []*ElementNode + Action *ActionNode } type ElementNode struct { @@ -22,6 +29,11 @@ type ElementNode struct { Pattern string } +type ActionNode struct { + Name string + Parameter string +} + func raiseSyntaxError(synErr *SyntaxError) { panic(synErr) } @@ -87,13 +99,34 @@ func (p *parser) parseProduction() *ProductionNode { if p.consume(tokenKindEOF) { return nil } + + var mod *ModifierNode + if p.consume(tokenKindModifierMarker) { + if !p.consume(tokenKindID) { + raiseSyntaxError(synErrNoModifierName) + } + name := p.lastTok.text + + var param string + if p.consume(tokenKindID) { + param = p.lastTok.text + } + + mod = &ModifierNode{ + Name: name, + Parameter: param, + } + } + if !p.consume(tokenKindID) { raiseSyntaxError(synErrNoProductionName) } lhs := p.lastTok.text + if !p.consume(tokenKindColon) { raiseSyntaxError(synErrNoColon) } + alt := p.parseAlternative() rhs := []*AlternativeNode{alt} for { @@ -103,12 +136,15 @@ func (p *parser) parseProduction() *ProductionNode { alt := p.parseAlternative() rhs = append(rhs, alt) } + if !p.consume(tokenKindSemicolon) { raiseSyntaxError(synErrNoSemicolon) } + return &ProductionNode{ - LHS: lhs, - RHS: rhs, + Modifier: mod, + LHS: lhs, + RHS: rhs, } } @@ -121,8 +157,28 @@ func (p *parser) parseAlternative() *AlternativeNode { } elems = append(elems, elem) } + + var act *ActionNode + if p.consume(tokenKindActionLeader) { + if !p.consume(tokenKindID) { + raiseSyntaxError(synErrNoActionName) + } + name := p.lastTok.text + + var param string + if p.consume(tokenKindID) { + param = p.lastTok.text + } + + act = &ActionNode{ + Name: name, + Parameter: param, + } + } + return &AlternativeNode{ Elements: elems, + Action: act, } } -- cgit v1.2.3