diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/token.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/token.go | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/token.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/token.go new file mode 100644 index 0000000..bcaa15f --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/token.go | |||
@@ -0,0 +1,272 @@ | |||
1 | package hclsyntax | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/apparentlymart/go-textseg/textseg" | ||
7 | "github.com/hashicorp/hcl2/hcl" | ||
8 | ) | ||
9 | |||
10 | // Token represents a sequence of bytes from some HCL code that has been | ||
11 | // tagged with a type and its range within the source file. | ||
12 | type Token struct { | ||
13 | Type TokenType | ||
14 | Bytes []byte | ||
15 | Range hcl.Range | ||
16 | } | ||
17 | |||
18 | // Tokens is a slice of Token. | ||
19 | type Tokens []Token | ||
20 | |||
21 | // TokenType is an enumeration used for the Type field on Token. | ||
22 | type TokenType rune | ||
23 | |||
24 | const ( | ||
25 | // Single-character tokens are represented by their own character, for | ||
26 | // convenience in producing these within the scanner. However, the values | ||
27 | // are otherwise arbitrary and just intended to be mnemonic for humans | ||
28 | // who might see them in debug output. | ||
29 | |||
30 | TokenOBrace TokenType = '{' | ||
31 | TokenCBrace TokenType = '}' | ||
32 | TokenOBrack TokenType = '[' | ||
33 | TokenCBrack TokenType = ']' | ||
34 | TokenOParen TokenType = '(' | ||
35 | TokenCParen TokenType = ')' | ||
36 | TokenOQuote TokenType = '«' | ||
37 | TokenCQuote TokenType = '»' | ||
38 | TokenOHeredoc TokenType = 'H' | ||
39 | TokenCHeredoc TokenType = 'h' | ||
40 | |||
41 | TokenStar TokenType = '*' | ||
42 | TokenSlash TokenType = '/' | ||
43 | TokenPlus TokenType = '+' | ||
44 | TokenMinus TokenType = '-' | ||
45 | TokenPercent TokenType = '%' | ||
46 | |||
47 | TokenEqual TokenType = '=' | ||
48 | TokenEqualOp TokenType = '≔' | ||
49 | TokenNotEqual TokenType = '≠' | ||
50 | TokenLessThan TokenType = '<' | ||
51 | TokenLessThanEq TokenType = '≤' | ||
52 | TokenGreaterThan TokenType = '>' | ||
53 | TokenGreaterThanEq TokenType = '≥' | ||
54 | |||
55 | TokenAnd TokenType = '∧' | ||
56 | TokenOr TokenType = '∨' | ||
57 | TokenBang TokenType = '!' | ||
58 | |||
59 | TokenDot TokenType = '.' | ||
60 | TokenComma TokenType = ',' | ||
61 | |||
62 | TokenEllipsis TokenType = '…' | ||
63 | TokenFatArrow TokenType = '⇒' | ||
64 | |||
65 | TokenQuestion TokenType = '?' | ||
66 | TokenColon TokenType = ':' | ||
67 | |||
68 | TokenTemplateInterp TokenType = '∫' | ||
69 | TokenTemplateControl TokenType = 'λ' | ||
70 | TokenTemplateSeqEnd TokenType = '∎' | ||
71 | |||
72 | TokenQuotedLit TokenType = 'Q' // might contain backslash escapes | ||
73 | TokenStringLit TokenType = 'S' // cannot contain backslash escapes | ||
74 | TokenNumberLit TokenType = 'N' | ||
75 | TokenIdent TokenType = 'I' | ||
76 | |||
77 | TokenComment TokenType = 'C' | ||
78 | |||
79 | TokenNewline TokenType = '\n' | ||
80 | TokenEOF TokenType = '␄' | ||
81 | |||
82 | // The rest are not used in the language but recognized by the scanner so | ||
83 | // we can generate good diagnostics in the parser when users try to write | ||
84 | // things that might work in other languages they are familiar with, or | ||
85 | // simply make incorrect assumptions about the HCL language. | ||
86 | |||
87 | TokenBitwiseAnd TokenType = '&' | ||
88 | TokenBitwiseOr TokenType = '|' | ||
89 | TokenBitwiseNot TokenType = '~' | ||
90 | TokenBitwiseXor TokenType = '^' | ||
91 | TokenStarStar TokenType = '➚' | ||
92 | TokenBacktick TokenType = '`' | ||
93 | TokenSemicolon TokenType = ';' | ||
94 | TokenTabs TokenType = '␉' | ||
95 | TokenInvalid TokenType = '�' | ||
96 | TokenBadUTF8 TokenType = '💩' | ||
97 | |||
98 | // TokenNil is a placeholder for when a token is required but none is | ||
99 | // available, e.g. when reporting errors. The scanner will never produce | ||
100 | // this as part of a token stream. | ||
101 | TokenNil TokenType = '\x00' | ||
102 | ) | ||
103 | |||
104 | func (t TokenType) GoString() string { | ||
105 | return fmt.Sprintf("hclsyntax.%s", t.String()) | ||
106 | } | ||
107 | |||
108 | type scanMode int | ||
109 | |||
110 | const ( | ||
111 | scanNormal scanMode = iota | ||
112 | scanTemplate | ||
113 | scanIdentOnly | ||
114 | ) | ||
115 | |||
116 | type tokenAccum struct { | ||
117 | Filename string | ||
118 | Bytes []byte | ||
119 | Pos hcl.Pos | ||
120 | Tokens []Token | ||
121 | } | ||
122 | |||
123 | func (f *tokenAccum) emitToken(ty TokenType, startOfs, endOfs int) { | ||
124 | // Walk through our buffer to figure out how much we need to adjust | ||
125 | // the start pos to get our end pos. | ||
126 | |||
127 | start := f.Pos | ||
128 | start.Column += startOfs - f.Pos.Byte // Safe because only ASCII spaces can be in the offset | ||
129 | start.Byte = startOfs | ||
130 | |||
131 | end := start | ||
132 | end.Byte = endOfs | ||
133 | b := f.Bytes[startOfs:endOfs] | ||
134 | for len(b) > 0 { | ||
135 | advance, seq, _ := textseg.ScanGraphemeClusters(b, true) | ||
136 | if (len(seq) == 1 && seq[0] == '\n') || (len(seq) == 2 && seq[0] == '\r' && seq[1] == '\n') { | ||
137 | end.Line++ | ||
138 | end.Column = 1 | ||
139 | } else { | ||
140 | end.Column++ | ||
141 | } | ||
142 | b = b[advance:] | ||
143 | } | ||
144 | |||
145 | f.Pos = end | ||
146 | |||
147 | f.Tokens = append(f.Tokens, Token{ | ||
148 | Type: ty, | ||
149 | Bytes: f.Bytes[startOfs:endOfs], | ||
150 | Range: hcl.Range{ | ||
151 | Filename: f.Filename, | ||
152 | Start: start, | ||
153 | End: end, | ||
154 | }, | ||
155 | }) | ||
156 | } | ||
157 | |||
158 | type heredocInProgress struct { | ||
159 | Marker []byte | ||
160 | StartOfLine bool | ||
161 | } | ||
162 | |||
163 | // checkInvalidTokens does a simple pass across the given tokens and generates | ||
164 | // diagnostics for tokens that should _never_ appear in HCL source. This | ||
165 | // is intended to avoid the need for the parser to have special support | ||
166 | // for them all over. | ||
167 | // | ||
168 | // Returns a diagnostics with no errors if everything seems acceptable. | ||
169 | // Otherwise, returns zero or more error diagnostics, though tries to limit | ||
170 | // repetition of the same information. | ||
171 | func checkInvalidTokens(tokens Tokens) hcl.Diagnostics { | ||
172 | var diags hcl.Diagnostics | ||
173 | |||
174 | toldBitwise := 0 | ||
175 | toldExponent := 0 | ||
176 | toldBacktick := 0 | ||
177 | toldSemicolon := 0 | ||
178 | toldTabs := 0 | ||
179 | toldBadUTF8 := 0 | ||
180 | |||
181 | for _, tok := range tokens { | ||
182 | switch tok.Type { | ||
183 | case TokenBitwiseAnd, TokenBitwiseOr, TokenBitwiseXor, TokenBitwiseNot: | ||
184 | if toldBitwise < 4 { | ||
185 | var suggestion string | ||
186 | switch tok.Type { | ||
187 | case TokenBitwiseAnd: | ||
188 | suggestion = " Did you mean boolean AND (\"&&\")?" | ||
189 | case TokenBitwiseOr: | ||
190 | suggestion = " Did you mean boolean OR (\"&&\")?" | ||
191 | case TokenBitwiseNot: | ||
192 | suggestion = " Did you mean boolean NOT (\"!\")?" | ||
193 | } | ||
194 | |||
195 | diags = append(diags, &hcl.Diagnostic{ | ||
196 | Severity: hcl.DiagError, | ||
197 | Summary: "Unsupported operator", | ||
198 | Detail: fmt.Sprintf("Bitwise operators are not supported.%s", suggestion), | ||
199 | Subject: &tok.Range, | ||
200 | }) | ||
201 | toldBitwise++ | ||
202 | } | ||
203 | case TokenStarStar: | ||
204 | if toldExponent < 1 { | ||
205 | diags = append(diags, &hcl.Diagnostic{ | ||
206 | Severity: hcl.DiagError, | ||
207 | Summary: "Unsupported operator", | ||
208 | Detail: "\"**\" is not a supported operator. Exponentiation is not supported as an operator.", | ||
209 | Subject: &tok.Range, | ||
210 | }) | ||
211 | |||
212 | toldExponent++ | ||
213 | } | ||
214 | case TokenBacktick: | ||
215 | // Only report for alternating (even) backticks, so we won't report both start and ends of the same | ||
216 | // backtick-quoted string. | ||
217 | if toldExponent < 4 && (toldExponent%2) == 0 { | ||
218 | diags = append(diags, &hcl.Diagnostic{ | ||
219 | Severity: hcl.DiagError, | ||
220 | Summary: "Invalid character", | ||
221 | Detail: "The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<<EOT\".", | ||
222 | Subject: &tok.Range, | ||
223 | }) | ||
224 | |||
225 | toldBacktick++ | ||
226 | } | ||
227 | case TokenSemicolon: | ||
228 | if toldSemicolon < 1 { | ||
229 | diags = append(diags, &hcl.Diagnostic{ | ||
230 | Severity: hcl.DiagError, | ||
231 | Summary: "Invalid character", | ||
232 | Detail: "The \";\" character is not valid. Use newlines to separate attributes and blocks, and commas to separate items in collection values.", | ||
233 | Subject: &tok.Range, | ||
234 | }) | ||
235 | |||
236 | toldSemicolon++ | ||
237 | } | ||
238 | case TokenTabs: | ||
239 | if toldTabs < 1 { | ||
240 | diags = append(diags, &hcl.Diagnostic{ | ||
241 | Severity: hcl.DiagError, | ||
242 | Summary: "Invalid character", | ||
243 | Detail: "Tab characters may not be used. The recommended indentation style is two spaces per indent.", | ||
244 | Subject: &tok.Range, | ||
245 | }) | ||
246 | |||
247 | toldTabs++ | ||
248 | } | ||
249 | case TokenBadUTF8: | ||
250 | if toldBadUTF8 < 1 { | ||
251 | diags = append(diags, &hcl.Diagnostic{ | ||
252 | Severity: hcl.DiagError, | ||
253 | Summary: "Invalid character encoding", | ||
254 | Detail: "All input files must be UTF-8 encoded. Ensure that UTF-8 encoding is selected in your editor.", | ||
255 | Subject: &tok.Range, | ||
256 | }) | ||
257 | |||
258 | toldBadUTF8++ | ||
259 | } | ||
260 | case TokenInvalid: | ||
261 | diags = append(diags, &hcl.Diagnostic{ | ||
262 | Severity: hcl.DiagError, | ||
263 | Summary: "Invalid character", | ||
264 | Detail: "This character is not used within the language.", | ||
265 | Subject: &tok.Range, | ||
266 | }) | ||
267 | |||
268 | toldTabs++ | ||
269 | } | ||
270 | } | ||
271 | return diags | ||
272 | } | ||