1. package chroma
    
  2. 
    
  3. import (
    
  4. 	"encoding/xml"
    
  5. 	"fmt"
    
  6. 	"strings"
    
  7. )
    
  8. 
    
  9. // A Mutator modifies the behaviour of the lexer.
    
  10. type Mutator interface {
    
  11. 	// Mutate the lexer state machine as it is processing.
    
  12. 	Mutate(state *LexerState) error
    
  13. }
    
  14. 
    
  15. // SerialisableMutator is a Mutator that can be serialised and deserialised.
    
  16. type SerialisableMutator interface {
    
  17. 	Mutator
    
  18. 	MutatorKind() string
    
  19. }
    
  20. 
    
  21. // A LexerMutator is an additional interface that a Mutator can implement
    
  22. // to modify the lexer when it is compiled.
    
  23. type LexerMutator interface {
    
  24. 	// MutateLexer can be implemented to mutate the lexer itself.
    
  25. 	//
    
  26. 	// Rules are the lexer rules, state is the state key for the rule the mutator is associated with.
    
  27. 	MutateLexer(rules CompiledRules, state string, rule int) error
    
  28. }
    
  29. 
    
  30. // A MutatorFunc is a Mutator that mutates the lexer state machine as it is processing.
    
  31. type MutatorFunc func(state *LexerState) error
    
  32. 
    
  33. func (m MutatorFunc) Mutate(state *LexerState) error { return m(state) } // nolint
    
  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 "mutators" }
    
  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. // Mutators applies a set of Mutators in order.
    
  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. // Include the given state.
    
  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. // Combined creates a new anonymous state from the given states, and pushes that state.
    
  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. // Push states onto the stack.
    
  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. // Pop state from the stack when rule matches.
    
  185. func Pop(n int) Mutator {
    
  186. 	return &popMutator{n}
    
  187. }
    
  188. 
    
  189. // Default returns a Rule that applies a set of Mutators.
    
  190. func Default(mutators ...Mutator) Rule {
    
  191. 	return Rule{Mutator: Mutators(mutators...)}
    
  192. }
    
  193. 
    
  194. // Stringify returns the raw string for a set of tokens.
    
  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. }