aboutsummaryrefslogtreecommitdiff
path: root/grammar
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 /grammar
parentSupport the escape sequecens \' and \\ in a string literal (diff)
downloadcotia-936b600ce23cce4350a730817a067a8926384baf.tar.gz
cotia-936b600ce23cce4350a730817a067a8926384baf.tar.xz
Use a pattern string defined by a string literal as its alias
Diffstat (limited to 'grammar')
-rw-r--r--grammar/grammar.go55
1 files changed, 42 insertions, 13 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