match - match.go
1 package match
2
3 import (
4 "errors"
5 "unsafe"
6 )
7
8 type stateValue[T comparable] struct {
9 states [256]uint32
10 value T
11 }
12
13 type StateMachine[T comparable] struct {
14 states []stateValue[T]
15 }
16
17 func New[T comparable]() *StateMachine[T] {
18 return &StateMachine[T]{
19 states: make([]stateValue[T], 2),
20 }
21 }
22
23 func (s *StateMachine[T]) AddString(str string, value T) error {
24 o, err := parse[T](str, simpleStart)
25 if err != nil {
26 return err
27 }
28
29 _, err = o.compile(s, 1, make(visitedSet), value)
30
31 return err
32 }
33
34 func (s *StateMachine[T]) Match(str string) T {
35 return s.states[s.matchState(str, 1)].value
36 }
37
38 func (s *StateMachine[T]) matchState(str string, state uint32) uint32 {
39 for _, c := range strToBytes(str) {
40 state = s.states[state].states[c]
41 }
42
43 return state
44 }
45
46 func strToBytes(str string) []byte {
47 return unsafe.Slice(unsafe.StringData(str), len(str))
48 }
49
50 type State[T comparable] struct {
51 sm *StateMachine[T]
52 state uint32
53 }
54
55 func (s *StateMachine[T]) MatchState(str string) State[T] {
56 return State[T]{
57 sm: s,
58 state: s.matchState(str, 1),
59 }
60 }
61
62 func (s *State[T]) Match(str string) T {
63 return s.sm.states[s.sm.matchState(str, s.state)].value
64 }
65
66 func (s *State[T]) MatchState(str string) State[T] {
67 return State[T]{
68 sm: s.sm,
69 state: s.sm.matchState(str, s.state),
70 }
71 }
72
73 var ErrAmbiguous = errors.New("ambiguous states")
74