annotate vendor/github.com/alecthomas/chroma/v2/regexp.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 package chroma
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 "fmt"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 "os"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 "path/filepath"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 "regexp"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 "sort"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9 "strings"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 "sync"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 "time"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 "unicode/utf8"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 "github.com/dlclark/regexp2"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17 // A Rule is the fundamental matching unit of the Regex lexer state machine.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 type Rule struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 Pattern string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 Type Emitter
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21 Mutator Mutator
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 // Words creates a regex that matches any of the given literal words.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 func Words(prefix, suffix string, words ...string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 sort.Slice(words, func(i, j int) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 return len(words[j]) < len(words[i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29 for i, word := range words {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 words[i] = regexp.QuoteMeta(word)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 return prefix + `(` + strings.Join(words, `|`) + `)` + suffix
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 // Tokenise text using lexer, returning tokens as a slice.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 func Tokenise(lexer Lexer, options *TokeniseOptions, text string) ([]Token, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 var out []Token
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 it, err := lexer.Tokenise(options, text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 for t := it(); t != EOF; t = it() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 out = append(out, t)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 return out, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 // Rules maps from state to a sequence of Rules.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 type Rules map[string][]Rule
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 // Rename clones rules then a rule.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 func (r Rules) Rename(oldRule, newRule string) Rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 r = r.Clone()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 r[newRule] = r[oldRule]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 delete(r, oldRule)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 return r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 // Clone returns a clone of the Rules.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 func (r Rules) Clone() Rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 out := map[string][]Rule{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 for key, rules := range r {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 out[key] = make([]Rule, len(rules))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 copy(out[key], rules)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 return out
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 // Merge creates a clone of "r" then merges "rules" into the clone.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 func (r Rules) Merge(rules Rules) Rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 out := r.Clone()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 for k, v := range rules.Clone() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 out[k] = v
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 return out
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 // MustNewLexer creates a new Lexer with deferred rules generation or panics.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 func MustNewLexer(config *Config, rulesFunc func() Rules) *RegexLexer {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 lexer, err := NewLexer(config, rulesFunc)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 panic(err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84 return lexer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 // NewLexer creates a new regex-based Lexer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89 // "rules" is a state machine transition map. Each key is a state. Values are sets of rules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 // that match input, optionally modify lexer state, and output tokens.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 func NewLexer(config *Config, rulesFunc func() Rules) (*RegexLexer, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 if config == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 config = &Config{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 for _, glob := range append(config.Filenames, config.AliasFilenames...) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 _, err := filepath.Match(glob, "")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 r := &RegexLexer{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 config: config,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 fetchRulesFunc: func() (Rules, error) { return rulesFunc(), nil },
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 // One-off code to generate XML lexers in the Chroma source tree.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 // var nameCleanRe = regexp.MustCompile(`[^-+A-Za-z0-9_]`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 // name := strings.ToLower(nameCleanRe.ReplaceAllString(config.Name, "_"))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 // data, err := Marshal(r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 // if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 // if errors.Is(err, ErrNotSerialisable) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 // fmt.Fprintf(os.Stderr, "warning: %q: %s\n", name, err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 // return r, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 // return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 // _, file, _, ok := runtime.Caller(2)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 // if !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 // panic("??")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 // fmt.Println(file)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 // if strings.Contains(file, "/lexers/") {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 // dir := filepath.Join(filepath.Dir(file), "embedded")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 // err = os.MkdirAll(dir, 0700)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 // if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 // return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 // filename := filepath.Join(dir, name) + ".xml"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 // fmt.Println(filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 // err = ioutil.WriteFile(filename, data, 0600)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 // if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 // return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 return r, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137 // Trace enables debug tracing.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 func (r *RegexLexer) Trace(trace bool) *RegexLexer {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 r.trace = trace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 return r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 // A CompiledRule is a Rule with a pre-compiled regex.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 // Note that regular expressions are lazily compiled on first use of the lexer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 type CompiledRule struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 Rule
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 Regexp *regexp2.Regexp
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 flags string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 // CompiledRules is a map of rule name to sequence of compiled rules in that rule.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 type CompiledRules map[string][]*CompiledRule
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155 // LexerState contains the state for a single lex.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 type LexerState struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 Lexer *RegexLexer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 Registry *LexerRegistry
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159 Text []rune
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 Pos int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 Rules CompiledRules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162 Stack []string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 State string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 Rule int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 // Group matches.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166 Groups []string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 // Named Group matches.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 NamedGroups map[string]string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 // Custum context for mutators.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 MutatorContext map[interface{}]interface{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 iteratorStack []Iterator
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 options *TokeniseOptions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 newlineAdded bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 // Set mutator context.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 func (l *LexerState) Set(key interface{}, value interface{}) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 l.MutatorContext[key] = value
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 // Get mutator context.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182 func (l *LexerState) Get(key interface{}) interface{} {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 return l.MutatorContext[key]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 // Iterator returns the next Token from the lexer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 func (l *LexerState) Iterator() Token { // nolint: gocognit
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 end := len(l.Text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 if l.newlineAdded {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 end--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192 for l.Pos < end && len(l.Stack) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 // Exhaust the iterator stack, if any.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194 for len(l.iteratorStack) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195 n := len(l.iteratorStack) - 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 t := l.iteratorStack[n]()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 if t == EOF {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 l.iteratorStack = l.iteratorStack[:n]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201 return t
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 l.State = l.Stack[len(l.Stack)-1]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 if l.Lexer.trace {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q\n", l.State, l.Pos, string(l.Text[l.Pos:]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 selectedRule, ok := l.Rules[l.State]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209 if !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 panic("unknown state " + l.State)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 ruleIndex, rule, groups, namedGroups := matchRules(l.Text, l.Pos, selectedRule)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 // No match.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214 if groups == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215 // From Pygments :\
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 // If the RegexLexer encounters a newline that is flagged as an error token, the stack is
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 // emptied and the lexer continues scanning in the 'root' state. This can help producing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219 // error-tolerant highlighting for erroneous input, e.g. when a single-line string is not
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220 // closed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 if l.Text[l.Pos] == '\n' && l.State != l.options.State {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222 l.Stack = []string{l.options.State}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 l.Pos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226 return Token{Error, string(l.Text[l.Pos-1 : l.Pos])}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 l.Rule = ruleIndex
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229 l.Groups = groups
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230 l.NamedGroups = namedGroups
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 l.Pos += utf8.RuneCountInString(groups[0])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232 if rule.Mutator != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233 if err := rule.Mutator.Mutate(l); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 panic(err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237 if rule.Type != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238 l.iteratorStack = append(l.iteratorStack, rule.Type.Emit(l.Groups, l))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241 // Exhaust the IteratorStack, if any.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 // Duplicate code, but eh.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243 for len(l.iteratorStack) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244 n := len(l.iteratorStack) - 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 t := l.iteratorStack[n]()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246 if t == EOF {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247 l.iteratorStack = l.iteratorStack[:n]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250 return t
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 // If we get to here and we still have text, return it as an error.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 if l.Pos != len(l.Text) && len(l.Stack) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255 value := string(l.Text[l.Pos:])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256 l.Pos = len(l.Text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257 return Token{Type: Error, Value: value}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 return EOF
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262 // RegexLexer is the default lexer implementation used in Chroma.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263 type RegexLexer struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264 registry *LexerRegistry // The LexerRegistry this Lexer is associated with, if any.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 config *Config
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266 analyser func(text string) float32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 trace bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 mu sync.Mutex
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270 compiled bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 rawRules Rules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272 rules map[string][]*CompiledRule
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 fetchRulesFunc func() (Rules, error)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274 compileOnce sync.Once
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 func (r *RegexLexer) String() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278 return r.config.Name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 // Rules in the Lexer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282 func (r *RegexLexer) Rules() (Rules, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283 if err := r.needRules(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286 return r.rawRules, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 // SetRegistry the lexer will use to lookup other lexers if necessary.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 func (r *RegexLexer) SetRegistry(registry *LexerRegistry) Lexer {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 r.registry = registry
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292 return r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295 // SetAnalyser sets the analyser function used to perform content inspection.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296 func (r *RegexLexer) SetAnalyser(analyser func(text string) float32) Lexer {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 r.analyser = analyser
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298 return r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 func (r *RegexLexer) AnalyseText(text string) float32 { // nolint
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302 if r.analyser != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303 return r.analyser(text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305 return 0.0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308 // SetConfig replaces the Config for this Lexer.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 func (r *RegexLexer) SetConfig(config *Config) *RegexLexer {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310 r.config = config
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 return r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314 func (r *RegexLexer) Config() *Config { // nolint
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315 return r.config
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318 // Regex compilation is deferred until the lexer is used. This is to avoid significant init() time costs.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319 func (r *RegexLexer) maybeCompile() (err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320 r.mu.Lock()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321 defer r.mu.Unlock()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322 if r.compiled {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325 for state, rules := range r.rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 for i, rule := range rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327 if rule.Regexp == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 pattern := "(?:" + rule.Pattern + ")"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 if rule.flags != "" {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330 pattern = "(?" + rule.flags + ")" + pattern
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332 pattern = `\G` + pattern
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 rule.Regexp, err = regexp2.Compile(pattern, regexp2.RE2)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335 return fmt.Errorf("failed to compile rule %s.%d: %s", state, i, err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337 rule.Regexp.MatchTimeout = time.Millisecond * 250
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341 restart:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 seen := map[LexerMutator]bool{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343 for state := range r.rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344 for i := 0; i < len(r.rules[state]); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 rule := r.rules[state][i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346 if compile, ok := rule.Mutator.(LexerMutator); ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 if seen[compile] {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348 return fmt.Errorf("saw mutator %T twice; this should not happen", compile)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 seen[compile] = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 if err := compile.MutateLexer(r.rules, state, i); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352 return err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354 // Process the rules again in case the mutator added/removed rules.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
356 // This sounds bad, but shouldn't be significant in practice.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
357 goto restart
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
358 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
359 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
360 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
361 r.compiled = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
362 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
363 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
364
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
365 func (r *RegexLexer) fetchRules() error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
366 rules, err := r.fetchRulesFunc()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
367 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
368 return fmt.Errorf("%s: failed to compile rules: %w", r.config.Name, err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
369 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
370 if _, ok := rules["root"]; !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
371 return fmt.Errorf("no \"root\" state")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
372 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
373 compiledRules := map[string][]*CompiledRule{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
374 for state, rules := range rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
375 compiledRules[state] = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
376 for _, rule := range rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
377 flags := ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
378 if !r.config.NotMultiline {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
379 flags += "m"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
380 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
381 if r.config.CaseInsensitive {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
382 flags += "i"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
383 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
384 if r.config.DotAll {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
385 flags += "s"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
386 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
387 compiledRules[state] = append(compiledRules[state], &CompiledRule{Rule: rule, flags: flags})
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
388 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
389 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
390
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
391 r.rawRules = rules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
392 r.rules = compiledRules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
393 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
394 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
395
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
396 func (r *RegexLexer) needRules() error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
397 var err error
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
398 if r.fetchRulesFunc != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
399 r.compileOnce.Do(func() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
400 err = r.fetchRules()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
401 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
402 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
403 if err := r.maybeCompile(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
404 return err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
405 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
406 return err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
407 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
408
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
409 func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
410 err := r.needRules()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
411 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
412 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
413 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
414 if options == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
415 options = defaultOptions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
416 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
417 if options.EnsureLF {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
418 text = ensureLF(text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
419 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
420 newlineAdded := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
421 if !options.Nested && r.config.EnsureNL && !strings.HasSuffix(text, "\n") {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
422 text += "\n"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
423 newlineAdded = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
424 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
425 state := &LexerState{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
426 Registry: r.registry,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
427 newlineAdded: newlineAdded,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
428 options: options,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
429 Lexer: r,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
430 Text: []rune(text),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
431 Stack: []string{options.State},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
432 Rules: r.rules,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
433 MutatorContext: map[interface{}]interface{}{},
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
434 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
435 return state.Iterator, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
436 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
437
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
438 // MustRules is like Rules() but will panic on error.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
439 func (r *RegexLexer) MustRules() Rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
440 rules, err := r.Rules()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
441 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
442 panic(err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
443 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
444 return rules
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
445 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
446
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
447 func matchRules(text []rune, pos int, rules []*CompiledRule) (int, *CompiledRule, []string, map[string]string) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
448 for i, rule := range rules {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
449 match, err := rule.Regexp.FindRunesMatchStartingAt(text, pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
450 if match != nil && err == nil && match.Index == pos {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
451 groups := []string{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
452 namedGroups := make(map[string]string)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
453 for _, g := range match.Groups() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
454 namedGroups[g.Name] = g.String()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
455 groups = append(groups, g.String())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
456 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
457 return i, rule, groups, namedGroups
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
458 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
459 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
460 return 0, &CompiledRule{}, nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
461 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
462
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
463 // replace \r and \r\n with \n
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
464 // same as strings.ReplaceAll but more efficient
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
465 func ensureLF(text string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
466 buf := make([]byte, len(text))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
467 var j int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
468 for i := 0; i < len(text); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
469 c := text[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
470 if c == '\r' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
471 if i < len(text)-1 && text[i+1] == '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
472 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
473 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
474 c = '\n'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
475 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
476 buf[j] = c
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
477 j++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
478 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
479 return string(buf[:j])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
480 }