remap.go

 1package chroma
 2
 3type remappingLexer struct {
 4	lexer  Lexer
 5	mapper func(Token) []Token
 6}
 7
 8// RemappingLexer remaps a token to a set of, potentially empty, tokens.
 9func RemappingLexer(lexer Lexer, mapper func(Token) []Token) Lexer {
10	return &remappingLexer{lexer, mapper}
11}
12
13func (r *remappingLexer) AnalyseText(text string) float32 {
14	return r.lexer.AnalyseText(text)
15}
16
17func (r *remappingLexer) SetAnalyser(analyser func(text string) float32) Lexer {
18	r.lexer.SetAnalyser(analyser)
19	return r
20}
21
22func (r *remappingLexer) SetRegistry(registry *LexerRegistry) Lexer {
23	r.lexer.SetRegistry(registry)
24	return r
25}
26
27func (r *remappingLexer) Config() *Config {
28	return r.lexer.Config()
29}
30
31func (r *remappingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
32	it, err := r.lexer.Tokenise(options, text)
33	if err != nil {
34		return nil, err
35	}
36	var buffer []Token
37	return func() Token {
38		for {
39			if len(buffer) > 0 {
40				t := buffer[0]
41				buffer = buffer[1:]
42				return t
43			}
44			t := it()
45			if t == EOF {
46				return t
47			}
48			buffer = r.mapper(t)
49		}
50	}, nil
51}
52
53// TypeMapping defines type maps for the TypeRemappingLexer.
54type TypeMapping []struct {
55	From, To TokenType
56	Words    []string
57}
58
59// TypeRemappingLexer remaps types of tokens coming from a parent Lexer.
60//
61// eg. Map "defvaralias" tokens of type NameVariable to NameFunction:
62//
63//	mapping := TypeMapping{
64//		{NameVariable, NameFunction, []string{"defvaralias"},
65//	}
66//	lexer = TypeRemappingLexer(lexer, mapping)
67func TypeRemappingLexer(lexer Lexer, mapping TypeMapping) Lexer {
68	// Lookup table for fast remapping.
69	lut := map[TokenType]map[string]TokenType{}
70	for _, rt := range mapping {
71		km, ok := lut[rt.From]
72		if !ok {
73			km = map[string]TokenType{}
74			lut[rt.From] = km
75		}
76		if len(rt.Words) == 0 {
77			km[""] = rt.To
78		} else {
79			for _, k := range rt.Words {
80				km[k] = rt.To
81			}
82		}
83	}
84	return RemappingLexer(lexer, func(t Token) []Token {
85		if k, ok := lut[t.Type]; ok {
86			if tt, ok := k[t.Value]; ok {
87				t.Type = tt
88			} else if tt, ok := k[""]; ok {
89				t.Type = tt
90			}
91		}
92		return []Token{t}
93	})
94}