...
1 package chroma
2
3 import (
4 "encoding/xml"
5 "fmt"
6 "strings"
7 )
8
9
10 type Mutator interface {
11
12 Mutate(state *LexerState) error
13 }
14
15
16 type SerialisableMutator interface {
17 Mutator
18 MutatorKind() string
19 }
20
21
22
23 type LexerMutator interface {
24
25
26
27 MutateLexer(rules CompiledRules, state string, rule int) error
28 }
29
30
31 type MutatorFunc func(state *LexerState) error
32
33 func (m MutatorFunc) Mutate(state *LexerState) error { return m(state) }
34
35 type multiMutator struct {
36 Mutators []Mutator `xml:"mutator"`
37 }
38
39 func (m *multiMutator) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
40 for {
41 token, err := d.Token()
42 if err != nil {
43 return err
44 }
45 switch token := token.(type) {
46 case xml.StartElement:
47 mutator, err := unmarshalMutator(d, token)
48 if err != nil {
49 return err
50 }
51 m.Mutators = append(m.Mutators, mutator)
52
53 case xml.EndElement:
54 return nil
55 }
56 }
57 }
58
59 func (m *multiMutator) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
60 name := xml.Name{Local: "mutators"}
61 if err := e.EncodeToken(xml.StartElement{Name: name}); err != nil {
62 return err
63 }
64 for _, m := range m.Mutators {
65 if err := marshalMutator(e, m); err != nil {
66 return err
67 }
68 }
69 return e.EncodeToken(xml.EndElement{Name: name})
70 }
71
72 func (m *multiMutator) MutatorKind() string { return "multiple" }
73
74 func (m *multiMutator) Mutate(state *LexerState) error {
75 for _, modifier := range m.Mutators {
76 if err := modifier.Mutate(state); err != nil {
77 return err
78 }
79 }
80 return nil
81 }
82
83
84 func Mutators(modifiers ...Mutator) Mutator {
85 return &multiMutator{modifiers}
86 }
87
88 type includeMutator struct {
89 State string `xml:"state,attr"`
90 }
91
92
93 func Include(state string) Rule {
94 return Rule{Mutator: &includeMutator{state}}
95 }
96
97 func (i *includeMutator) MutatorKind() string { return "include" }
98
99 func (i *includeMutator) Mutate(s *LexerState) error {
100 return fmt.Errorf("should never reach here Include(%q)", i.State)
101 }
102
103 func (i *includeMutator) MutateLexer(rules CompiledRules, state string, rule int) error {
104 includedRules, ok := rules[i.State]
105 if !ok {
106 return fmt.Errorf("invalid include state %q", i.State)
107 }
108 rules[state] = append(rules[state][:rule], append(includedRules, rules[state][rule+1:]...)...)
109 return nil
110 }
111
112 type combinedMutator struct {
113 States []string `xml:"state,attr"`
114 }
115
116 func (c *combinedMutator) MutatorKind() string { return "combined" }
117
118
119 func Combined(states ...string) Mutator {
120 return &combinedMutator{states}
121 }
122
123 func (c *combinedMutator) Mutate(s *LexerState) error {
124 return fmt.Errorf("should never reach here Combined(%v)", c.States)
125 }
126
127 func (c *combinedMutator) MutateLexer(rules CompiledRules, state string, rule int) error {
128 name := "__combined_" + strings.Join(c.States, "__")
129 if _, ok := rules[name]; !ok {
130 combined := []*CompiledRule{}
131 for _, state := range c.States {
132 rules, ok := rules[state]
133 if !ok {
134 return fmt.Errorf("invalid combine state %q", state)
135 }
136 combined = append(combined, rules...)
137 }
138 rules[name] = combined
139 }
140 rules[state][rule].Mutator = Push(name)
141 return nil
142 }
143
144 type pushMutator struct {
145 States []string `xml:"state,attr"`
146 }
147
148 func (p *pushMutator) MutatorKind() string { return "push" }
149
150 func (p *pushMutator) Mutate(s *LexerState) error {
151 if len(p.States) == 0 {
152 s.Stack = append(s.Stack, s.State)
153 } else {
154 for _, state := range p.States {
155 if state == "#pop" {
156 s.Stack = s.Stack[:len(s.Stack)-1]
157 } else {
158 s.Stack = append(s.Stack, state)
159 }
160 }
161 }
162 return nil
163 }
164
165
166 func Push(states ...string) Mutator {
167 return &pushMutator{states}
168 }
169
170 type popMutator struct {
171 Depth int `xml:"depth,attr"`
172 }
173
174 func (p *popMutator) MutatorKind() string { return "pop" }
175
176 func (p *popMutator) Mutate(state *LexerState) error {
177 if len(state.Stack) == 0 {
178 return fmt.Errorf("nothing to pop")
179 }
180 state.Stack = state.Stack[:len(state.Stack)-p.Depth]
181 return nil
182 }
183
184
185 func Pop(n int) Mutator {
186 return &popMutator{n}
187 }
188
189
190 func Default(mutators ...Mutator) Rule {
191 return Rule{Mutator: Mutators(mutators...)}
192 }
193
194
195 func Stringify(tokens ...Token) string {
196 out := []string{}
197 for _, t := range tokens {
198 out = append(out, t.Value)
199 }
200 return strings.Join(out, "")
201 }
202
View as plain text