1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
package spec
import (
"fmt"
"regexp"
"strings"
)
const lexKindPattern = "[A-Za-z_][0-9A-Za-z_]*"
var lexKindRE = regexp.MustCompile(lexKindPattern)
type LexKind string
const LexKindNil = LexKind("")
func (k LexKind) String() string {
return string(k)
}
func (k LexKind) validate() error {
if k == "" {
return fmt.Errorf("kind doesn't allow to be the empty string")
}
if !lexKindRE.Match([]byte(k)) {
return fmt.Errorf("kind must be %v", lexKindPattern)
}
return nil
}
type LexPattern string
func (p LexPattern) validate() error {
if p == "" {
return fmt.Errorf("pattern doesn't allow to be the empty string")
}
return nil
}
type LexEntry struct {
Kind LexKind `json:"kind"`
Pattern LexPattern `json:"pattern"`
}
func (e *LexEntry) validate() error {
err := e.Kind.validate()
if err != nil {
return err
}
err = e.Pattern.validate()
if err != nil {
return err
}
return nil
}
type LexSpec struct {
Entries []*LexEntry `json:"entries"`
}
func (s *LexSpec) Validate() error {
if len(s.Entries) <= 0 {
return fmt.Errorf("the lexical specification must have at least one entry")
}
{
var errs []error
for i, e := range s.Entries {
err := e.validate()
if err != nil {
errs = append(errs, fmt.Errorf("entry #%v: %w", i+1, err))
}
}
if len(errs) > 0 {
var b strings.Builder
fmt.Fprintf(&b, "%v", errs[0])
for _, err := range errs[1:] {
fmt.Fprintf(&b, "\n%v", err)
}
return fmt.Errorf(b.String())
}
}
{
ks := map[string]struct{}{}
for _, e := range s.Entries {
if _, exist := ks[e.Kind.String()]; exist {
return fmt.Errorf("kinds `%v` are duplicates", e.Kind)
}
ks[e.Kind.String()] = struct{}{}
}
}
return nil
}
type TransitionTable struct {
InitialState int `json:"initial_state"`
AcceptingStates map[int]int `json:"accepting_states"`
Transition [][]int `json:"transition"`
}
type CompiledLexSpec struct {
Kinds []LexKind `json:"kinds"`
DFA *TransitionTable `json:"dfa"`
}
|