aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-08-28 11:03:09 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-08-28 16:59:27 +0900
commit936b600ce23cce4350a730817a067a8926384baf (patch)
tree23467c2a49ee4795a0479d960addc1bb747b2c7b
parentSupport the escape sequecens \' and \\ in a string literal (diff)
downloadurubu-936b600ce23cce4350a730817a067a8926384baf.tar.gz
urubu-936b600ce23cce4350a730817a067a8926384baf.tar.xz
Use a pattern string defined by a string literal as its alias
-rw-r--r--grammar/grammar.go55
-rw-r--r--spec/parser.go12
2 files changed, 49 insertions, 18 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go
index b911ee2..2f5f3f8 100644
--- a/grammar/grammar.go
+++ b/grammar/grammar.go
@@ -292,25 +292,34 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT
anonPat2Sym := map[string]symbol{}
sym2AnonPat := map[symbol]string{}
+ aliases := map[symbol]string{}
{
+ knownPats := map[string]struct{}{}
anonPats := []string{}
+ literalPats := map[string]struct{}{}
for _, prod := range root.Productions {
for _, alt := range prod.RHS {
for _, elem := range alt.Elements {
if elem.Pattern == "" {
continue
}
- exist := false
- for _, p := range anonPats {
- if p == elem.Pattern {
- exist = true
- break
- }
+
+ var pattern string
+ if elem.Literally {
+ pattern = mlspec.EscapePattern(elem.Pattern)
+ } else {
+ pattern = elem.Pattern
}
- if exist {
+
+ if _, ok := knownPats[pattern]; ok {
continue
}
- anonPats = append(anonPats, elem.Pattern)
+
+ knownPats[pattern] = struct{}{}
+ anonPats = append(anonPats, pattern)
+ if elem.Literally {
+ literalPats[pattern] = struct{}{}
+ }
}
}
}
@@ -326,6 +335,10 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT
anonPat2Sym[p] = sym
sym2AnonPat[sym] = p
+ if _, ok := literalPats[p]; ok {
+ aliases[sym] = p
+ }
+
entries = append(entries, &mlspec.LexEntry{
Kind: mlspec.LexKindName(kind),
Pattern: mlspec.LexPattern(p),
@@ -335,7 +348,6 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT
skipKinds := []mlspec.LexKindName{}
skipSyms := []string{}
- aliases := map[symbol]string{}
for _, prod := range root.LexProductions {
if sym, exist := symTab.toSymbol(prod.LHS); exist {
if sym == errSym {
@@ -449,10 +461,20 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
}
alt := prod.RHS[0]
+ elem := alt.Elements[0]
+
+ var pattern string
+ var alias string
+ if elem.Literally {
+ pattern = mlspec.EscapePattern(elem.Pattern)
+ alias = elem.Pattern
+ } else {
+ pattern = elem.Pattern
+ }
+
var skip bool
var push mlspec.LexModeName
var pop bool
- var alias string
if alt.Directive != nil {
dir := alt.Directive
switch dir.Name {
@@ -509,7 +531,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
return &mlspec.LexEntry{
Modes: modes,
Kind: mlspec.LexKindName(prod.LHS),
- Pattern: mlspec.LexPattern(alt.Elements[0].Pattern),
+ Pattern: mlspec.LexPattern(pattern),
Push: push,
Pop: pop,
}, skip, alias, nil, nil
@@ -610,11 +632,18 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
for i, elem := range alt.Elements {
var sym symbol
if elem.Pattern != "" {
+ var pattern string
+ if elem.Literally {
+ pattern = mlspec.EscapePattern(elem.Pattern)
+ } else {
+ pattern = elem.Pattern
+ }
+
var ok bool
- sym, ok = anonPat2Sym[elem.Pattern]
+ sym, ok = anonPat2Sym[pattern]
if !ok {
// All patterns are assumed to be pre-detected, so it's a bug if we cannot find them here.
- return nil, fmt.Errorf("pattern '%v' is undefined", elem.Pattern)
+ return nil, fmt.Errorf("pattern '%v' is undefined", pattern)
}
} else {
var ok bool
diff --git a/spec/parser.go b/spec/parser.go
index 9778521..71ee50b 100644
--- a/spec/parser.go
+++ b/spec/parser.go
@@ -36,9 +36,10 @@ type AlternativeNode struct {
}
type ElementNode struct {
- ID string
- Pattern string
- Pos Position
+ ID string
+ Pattern string
+ Literally bool
+ Pos Position
}
type DirectiveNode struct {
@@ -407,8 +408,9 @@ func (p *parser) parseElement() *ElementNode {
}
case p.consume(tokenKindStringLiteral):
return &ElementNode{
- Pattern: mlspec.EscapePattern(p.lastTok.text),
- Pos: p.lastTok.pos,
+ Pattern: p.lastTok.text,
+ Literally: true,
+ Pos: p.lastTok.pos,
}
}
return nil