-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscan_lua.go
More file actions
111 lines (106 loc) · 3.24 KB
/
Copy pathscan_lua.go
File metadata and controls
111 lines (106 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package highlight
import "strings"
// luaKeywords is the reserved words, plus the three literals that read
// as keywords.
var luaKeywords = words(
"and", "break", "do", "else", "elseif", "end", "false", "for",
"function", "goto", "if", "in", "local", "nil", "not", "or",
"repeat", "return", "then", "true", "until", "while",
)
// luaNames is the standard library and the one global a Neovim config
// is written against. Lua's library is small enough to name, which is
// what makes it worth naming: everything else that gets the name color
// is a call, recognized by the paren after it.
var luaNames = words(
"assert", "collectgarbage", "coroutine", "debug", "dofile",
"error", "getmetatable", "io", "ipairs", "load", "loadstring",
"math", "next", "os", "package", "pairs", "pcall", "print",
"rawequal", "rawget", "rawlen", "rawset", "require", "select",
"setmetatable", "string", "table", "tonumber", "tostring",
"type", "unpack", "vim", "xpcall",
)
// scanLua tokenizes one line of Lua, carrying the two things that
// outlive a line: a long string and a long comment, both written in
// double brackets.
//
// Only the level-0 brackets, [[ and ]]. A long string can be opened
// with any number of equals signs -- [==[ closes only at ]==] -- which
// is a depth this carry cannot hold, and which exists for text that
// contains a ]]. Neither the configs nor the articles here have one, and
// the cost of meeting one is code colored as a string until the next
// ]], not a line the reader loses.
//
// A quoted string is not a carry: a newline inside one is an error, and
// a long string is what Lua offers instead.
func scanLua(st state, line string) ([]token, state) {
var ts tokens
for i := 0; i < len(line); {
switch st {
case stateRawString:
n, closed := ts.drain("s", line[i:], "]]")
i += n
if !closed {
return ts.done(), st
}
st = stateCode
continue
case stateBlockComment:
n, closed := ts.drain("c", line[i:], "]]")
i += n
if !closed {
return ts.done(), st
}
st = stateCode
continue
}
c := line[i]
switch {
case strings.HasPrefix(line[i:], "--[["):
// Before the line comment below, which it starts with.
ts.add("c", line[i:i+4])
i += 4
st = stateBlockComment
case strings.HasPrefix(line[i:], "--"):
ts.add("c", line[i:])
return ts.done(), st
case strings.HasPrefix(line[i:], "[["):
ts.add("s", line[i:i+2])
i += 2
st = stateRawString
case c == '"' || c == '\'':
n := scanQuoted(line[i:], c)
ts.add("s", line[i:i+n])
i += n
case isDigit(c) || (c == '.' && i+1 < len(line) && isDigit(line[i+1])):
n := scanNumber(line[i:])
ts.add("m", line[i:i+n])
i += n
case isIdentStart(c):
j := i + 1
for j < len(line) && isIdent(line[j]) {
j++
}
word := line[i:j]
switch {
case luaKeywords[word]:
ts.add("k", word)
case luaNames[word]:
ts.add("n", word)
case j < len(line) && line[j] == '(':
ts.add("n", word)
case j < len(line) && (line[j] == '"' || line[j] == '\''):
// A call whose only argument is a string may drop
// the parens: require("x") and require"x" are the
// same call.
ts.add("n", word)
default:
ts.add("", word)
}
i = j
default:
ts.add("", line[i:i+1])
i++
}
}
return ts.done(), st
}