diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-08-28 11:03:09 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-08-28 16:59:27 +0900 |
commit | 936b600ce23cce4350a730817a067a8926384baf (patch) | |
tree | 23467c2a49ee4795a0479d960addc1bb747b2c7b | |
parent | Support the escape sequecens \' and \\ in a string literal (diff) | |
download | urubu-936b600ce23cce4350a730817a067a8926384baf.tar.gz urubu-936b600ce23cce4350a730817a067a8926384baf.tar.xz |
Use a pattern string defined by a string literal as its alias
-rw-r--r-- | grammar/grammar.go | 55 | ||||
-rw-r--r-- | spec/parser.go | 12 |
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 |