aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-09-22 23:36:19 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-09-22 23:36:19 +0900
commitcf4f53332e9d99a3a9eccfe69e70f98769862c3a (patch)
tree5963589f931d899f2855b5b25919e8368c3575d5
parentAdd name field to the lexical specification (diff)
downloadtre-cf4f53332e9d99a3a9eccfe69e70f98769862c3a.tar.gz
tre-cf4f53332e9d99a3a9eccfe69e70f98769862c3a.tar.xz
Keep the order of AST nodes constant
-rw-r--r--compiler/compiler.go13
-rw-r--r--compiler/dfa_test.go7
-rw-r--r--compiler/parser.go36
-rw-r--r--compiler/parser_test.go14
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)