diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-07-31 16:30:56 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-07-31 16:30:56 +0900 |
commit | 7db2c43fb274dcd1302f10fe20825b27f08ea5be (patch) | |
tree | 27c3a2bf2de6c0793a841682d4e33875d8e570bc /grammar/grammar.go | |
parent | Detect duplicate names between terminals and non-terminals (diff) | |
download | urubu-7db2c43fb274dcd1302f10fe20825b27f08ea5be.tar.gz urubu-7db2c43fb274dcd1302f10fe20825b27f08ea5be.tar.xz |
Write terminals to a description file
Diffstat (limited to 'grammar/grammar.go')
-rw-r--r-- | grammar/grammar.go | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go index 3268902..70387e2 100644 --- a/grammar/grammar.go +++ b/grammar/grammar.go @@ -196,43 +196,13 @@ type symbolTableAndLexSpec struct { } func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolTableAndLexSpec, error) { + // Anonymous patterns take precedence over explicitly defined lexical specifications (named patterns). + // Thus anonymous patterns must be registered to `symTab` and `entries` before named patterns. symTab := newSymbolTable() - skipKinds := []mlspec.LexKind{} - skipSyms := []string{} entries := []*mlspec.LexEntry{} - for _, prod := range root.LexProductions { - if _, exist := symTab.toSymbol(prod.LHS); exist { - b.errs = append(b.errs, &verr.SpecError{ - Cause: semErrDuplicateTerminal, - Detail: prod.LHS, - Row: prod.Pos.Row, - }) - continue - } - - _, err := symTab.registerTerminalSymbol(prod.LHS) - if err != nil { - return nil, err - } - - entry, skip, specErr, err := genLexEntry(prod) - if err != nil { - return nil, err - } - if specErr != nil { - b.errs = append(b.errs, specErr) - continue - } - if skip { - skipKinds = append(skipKinds, mlspec.LexKind(prod.LHS)) - skipSyms = append(skipSyms, prod.LHS) - } - entries = append(entries, entry) - } anonPat2Sym := map[string]symbol{} sym2AnonPat := map[symbol]string{} - var anonEntries []*mlspec.LexEntry { anonPats := []string{} for _, prod := range root.Productions { @@ -263,18 +233,48 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT if err != nil { return nil, err } + anonPat2Sym[p] = sym sym2AnonPat[sym] = p - anonEntries = append(anonEntries, &mlspec.LexEntry{ + entries = append(entries, &mlspec.LexEntry{ Kind: mlspec.LexKind(kind), Pattern: mlspec.LexPattern(p), }) } } - // Anonymous patterns take precedence over explicitly defined lexical specifications. - entries = append(anonEntries, entries...) + skipKinds := []mlspec.LexKind{} + skipSyms := []string{} + for _, prod := range root.LexProductions { + if _, exist := symTab.toSymbol(prod.LHS); exist { + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrDuplicateTerminal, + Detail: prod.LHS, + Row: prod.Pos.Row, + }) + continue + } + + _, err := symTab.registerTerminalSymbol(prod.LHS) + if err != nil { + return nil, err + } + + entry, skip, specErr, err := genLexEntry(prod) + if err != nil { + return nil, err + } + if specErr != nil { + b.errs = append(b.errs, specErr) + continue + } + if skip { + skipKinds = append(skipKinds, mlspec.LexKind(prod.LHS)) + skipSyms = append(skipSyms, prod.LHS) + } + entries = append(entries, entry) + } checkedFragments := map[string]struct{}{} for _, fragment := range root.Fragments { @@ -662,12 +662,12 @@ func Compile(gram *Grammar, opts ...compileOption) (*spec.CompiledGrammar, error skip[modeNum] = skipRec } - terms, err := gram.symbolTable.getTerminalTexts() + terms, err := gram.symbolTable.terminalTexts() if err != nil { return nil, err } - nonTerms, err := gram.symbolTable.getNonTerminalTexts() + nonTerms, err := gram.symbolTable.nonTerminalTexts() if err != nil { return nil, err } |