diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-09-22 23:36:19 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-09-22 23:36:19 +0900 |
commit | cf4f53332e9d99a3a9eccfe69e70f98769862c3a (patch) | |
tree | 5963589f931d899f2855b5b25919e8368c3575d5 | |
parent | Add name field to the lexical specification (diff) | |
download | tre-cf4f53332e9d99a3a9eccfe69e70f98769862c3a.tar.gz tre-cf4f53332e9d99a3a9eccfe69e70f98769862c3a.tar.xz |
Keep the order of AST nodes constant
-rw-r--r-- | compiler/compiler.go | 13 | ||||
-rw-r--r-- | compiler/dfa_test.go | 7 | ||||
-rw-r--r-- | compiler/parser.go | 36 | ||||
-rw-r--r-- | compiler/parser_test.go | 14 |
4 files changed, 50 insertions, 20 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go index 0c89737..3469044 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -201,8 +201,19 @@ func compile(entries []*spec.LexEntry, modeName2ID map[spec.LexModeName]spec.Lex var root astNode var symTab *symbolTable { + pats := make([]*patternEntry, len(patterns)+1) + pats[spec.LexModeKindIDNil] = &patternEntry{ + id: spec.LexModeKindIDNil, + } + for id, pattern := range patterns { + pats[id] = &patternEntry{ + id: id, + pattern: pattern, + } + } + var err error - root, symTab, err = parse(patterns, fragmentPatterns) + root, symTab, err = parse(pats, fragmentPatterns) if err != nil { return nil, err } diff --git a/compiler/dfa_test.go b/compiler/dfa_test.go index 2683815..74c9ba8 100644 --- a/compiler/dfa_test.go +++ b/compiler/dfa_test.go @@ -7,8 +7,11 @@ import ( ) func TestGenDFA(t *testing.T) { - root, symTab, err := parse(map[spec.LexModeKindID][]byte{ - 1: []byte("(a|b)*abb"), + root, symTab, err := parse([]*patternEntry{ + { + id: spec.LexModeKindIDMin, + pattern: []byte("(a|b)*abb"), + }, }, nil) if err != nil { t.Fatal(err) diff --git a/compiler/parser.go b/compiler/parser.go index 1c9126a..55b8238 100644 --- a/compiler/parser.go +++ b/compiler/parser.go @@ -78,8 +78,13 @@ func genSymTab(symTab *symbolTable, node astNode) *symbolTable { return symTab } -func parse(regexps map[spec.LexModeKindID][]byte, fragments map[string][]byte) (astNode, *symbolTable, error) { - if len(regexps) == 0 { +type patternEntry struct { + id spec.LexModeKindID + pattern []byte +} + +func parse(pats []*patternEntry, fragments map[string][]byte) (astNode, *symbolTable, error) { + if len(pats) == 0 { return nil, nil, fmt.Errorf("parse() needs at least one token entry") } @@ -91,7 +96,7 @@ func parse(regexps map[spec.LexModeKindID][]byte, fragments map[string][]byte) ( fragmentASTs = map[string]astNode{} } - root, err := parseRegexp(regexps, fragmentASTs) + root, err := parseRegexp(pats, fragmentASTs) if err != nil { return nil, nil, err } @@ -161,17 +166,22 @@ func parseFragments(fragments map[string][]byte) (map[string]astNode, error) { return fragmentASTs, nil } -func parseRegexp(regexps map[spec.LexModeKindID][]byte, fragmentASTs map[string]astNode) (astNode, error) { +func parseRegexp(pats []*patternEntry, fragmentASTs map[string]astNode) (astNode, error) { symPos := symbolPositionMin var root astNode var perrs []*ParseError - for id, pattern := range regexps { - p := newParser(bytes.NewReader(pattern)) + + for _, pat := range pats { + if pat.id == spec.LexModeKindIDNil { + continue + } + + p := newParser(bytes.NewReader(pat.pattern)) ast, err := p.parse() if err != nil { perrs = append(perrs, &ParseError{ - ID: id, - Pattern: pattern, + ID: pat.id, + Pattern: pat.pattern, Cause: err, Details: p.errMsgDetails, }) @@ -180,18 +190,18 @@ func parseRegexp(regexps map[spec.LexModeKindID][]byte, fragmentASTs map[string] remains := applyFragments(ast, fragmentASTs) if len(remains) > 0 { perrs = append(perrs, &ParseError{ - ID: id, - Pattern: pattern, + ID: pat.id, + Pattern: pat.pattern, Cause: fmt.Errorf("undefined fragment: %+v", remains), }) continue } - ast = newConcatNode(ast, newEndMarkerNode(id)) + ast = newConcatNode(ast, newEndMarkerNode(pat.id)) symPos, err = positionSymbols(ast, symPos) if err != nil { perrs = append(perrs, &ParseError{ - ID: id, - Pattern: pattern, + ID: pat.id, + Pattern: pat.pattern, Cause: err, Details: p.errMsgDetails, }) diff --git a/compiler/parser_test.go b/compiler/parser_test.go index 30e6130..7c33fb4 100644 --- a/compiler/parser_test.go +++ b/compiler/parser_test.go @@ -1199,8 +1199,11 @@ func TestParse(t *testing.T) { for kind, pattern := range tt.fragments { fragments[kind] = []byte(pattern) } - ast, _, err := parse(map[spec.LexModeKindID][]byte{ - 1: []byte(tt.pattern), + ast, _, err := parse([]*patternEntry{ + { + id: spec.LexModeKindIDMin, + pattern: []byte(tt.pattern), + }, }, fragments) if tt.syntaxError != nil { // printAST(os.Stdout, ast, "", "", false) @@ -1239,8 +1242,11 @@ func TestParse(t *testing.T) { } func TestParse_FollowAndSymbolTable(t *testing.T) { - root, symTab, err := parse(map[spec.LexModeKindID][]byte{ - 1: []byte("(a|b)*abb"), + root, symTab, err := parse([]*patternEntry{ + { + id: spec.LexModeKindIDMin, + pattern: []byte("(a|b)*abb"), + }, }, nil) if err != nil { t.Fatal(err) |