1 | #ifndef NVIM_VIML_PARSER_EXPRESSIONS_H |
2 | #define NVIM_VIML_PARSER_EXPRESSIONS_H |
3 | |
4 | #include <stddef.h> |
5 | #include <stdint.h> |
6 | #include <stdbool.h> |
7 | |
8 | #include "nvim/types.h" |
9 | #include "nvim/viml/parser/parser.h" |
10 | #include "nvim/eval/typval.h" |
11 | |
12 | // Defines whether to ignore case: |
13 | // == kCCStrategyUseOption |
14 | // ==# kCCStrategyMatchCase |
15 | // ==? kCCStrategyIgnoreCase |
16 | typedef enum { |
17 | kCCStrategyUseOption = 0, // 0 for xcalloc |
18 | kCCStrategyMatchCase = '#', |
19 | kCCStrategyIgnoreCase = '?', |
20 | } ExprCaseCompareStrategy; |
21 | |
22 | /// Lexer token type |
23 | typedef enum { |
24 | kExprLexInvalid = 0, ///< Invalid token, indicaten an error. |
25 | kExprLexMissing, ///< Missing token, for use in parser. |
26 | kExprLexSpacing, ///< Spaces, tabs, newlines, etc. |
27 | kExprLexEOC, ///< End of command character: NL, |, just end of stream. |
28 | |
29 | kExprLexQuestion, ///< Question mark, for use in ternary. |
30 | kExprLexColon, ///< Colon, for use in ternary. |
31 | kExprLexOr, ///< Logical or operator. |
32 | kExprLexAnd, ///< Logical and operator. |
33 | kExprLexComparison, ///< One of the comparison operators. |
34 | kExprLexPlus, ///< Plus sign. |
35 | kExprLexMinus, ///< Minus sign. |
36 | kExprLexDot, ///< Dot: either concat or subscript, also part of the float. |
37 | kExprLexMultiplication, ///< Multiplication, division or modulo operator. |
38 | |
39 | kExprLexNot, ///< Not: !. |
40 | |
41 | kExprLexNumber, ///< Integer number literal, or part of a float. |
42 | kExprLexSingleQuotedString, ///< Single quoted string literal. |
43 | kExprLexDoubleQuotedString, ///< Double quoted string literal. |
44 | kExprLexOption, ///< &optionname option value. |
45 | kExprLexRegister, ///< @r register value. |
46 | kExprLexEnv, ///< Environment $variable value. |
47 | kExprLexPlainIdentifier, ///< Identifier without scope: `abc`, `foo#bar`. |
48 | |
49 | kExprLexBracket, ///< Bracket, either opening or closing. |
50 | kExprLexFigureBrace, ///< Figure brace, either opening or closing. |
51 | kExprLexParenthesis, ///< Parenthesis, either opening or closing. |
52 | kExprLexComma, ///< Comma. |
53 | kExprLexArrow, ///< Arrow, like from lambda expressions. |
54 | kExprLexAssignment, ///< Assignment: `=` or `{op}=`. |
55 | // XXX When modifying this enum you need to also modify eltkn_type_tab in |
56 | // expressions.c and tests and, possibly, viml_pexpr_repr_token. |
57 | } LexExprTokenType; |
58 | |
59 | typedef enum { |
60 | kExprCmpEqual, ///< Equality, unequality. |
61 | kExprCmpMatches, ///< Matches regex, not matches regex. |
62 | kExprCmpGreater, ///< `>` or `<=` |
63 | kExprCmpGreaterOrEqual, ///< `>=` or `<`. |
64 | kExprCmpIdentical, ///< `is` or `isnot` |
65 | } ExprComparisonType; |
66 | |
67 | /// All possible option scopes |
68 | typedef enum { |
69 | kExprOptScopeUnspecified = 0, |
70 | kExprOptScopeGlobal = 'g', |
71 | kExprOptScopeLocal = 'l', |
72 | } ExprOptScope; |
73 | |
74 | /// All possible assignment types: `=` and `{op}=`. |
75 | typedef enum { |
76 | kExprAsgnPlain = 0, ///< Plain assignment: `=`. |
77 | kExprAsgnAdd, ///< Assignment augmented with addition: `+=`. |
78 | kExprAsgnSubtract, ///< Assignment augmented with subtraction: `-=`. |
79 | kExprAsgnConcat, ///< Assignment augmented with concatenation: `.=`. |
80 | } ExprAssignmentType; |
81 | |
82 | #define EXPR_OPT_SCOPE_LIST \ |
83 | ((char[]){ kExprOptScopeGlobal, kExprOptScopeLocal }) |
84 | |
85 | /// All possible variable scopes |
86 | typedef enum { |
87 | kExprVarScopeMissing = 0, |
88 | kExprVarScopeScript = 's', |
89 | kExprVarScopeGlobal = 'g', |
90 | kExprVarScopeVim = 'v', |
91 | kExprVarScopeBuffer = 'b', |
92 | kExprVarScopeWindow = 'w', |
93 | kExprVarScopeTabpage = 't', |
94 | kExprVarScopeLocal = 'l', |
95 | kExprVarScopeArguments = 'a', |
96 | } ExprVarScope; |
97 | |
98 | #define EXPR_VAR_SCOPE_LIST \ |
99 | ((char[]) { \ |
100 | kExprVarScopeScript, kExprVarScopeGlobal, kExprVarScopeVim, \ |
101 | kExprVarScopeBuffer, kExprVarScopeWindow, kExprVarScopeTabpage, \ |
102 | kExprVarScopeLocal, kExprVarScopeBuffer, kExprVarScopeArguments, \ |
103 | }) |
104 | |
105 | /// Lexer token |
106 | typedef struct { |
107 | ParserPosition start; |
108 | size_t len; |
109 | LexExprTokenType type; |
110 | union { |
111 | struct { |
112 | ExprComparisonType type; ///< Comparison type. |
113 | ExprCaseCompareStrategy ccs; ///< Case comparison strategy. |
114 | bool inv; ///< True if comparison is to be inverted. |
115 | } cmp; ///< For kExprLexComparison. |
116 | |
117 | struct { |
118 | enum { |
119 | kExprLexMulMul, ///< Real multiplication. |
120 | kExprLexMulDiv, ///< Division. |
121 | kExprLexMulMod, ///< Modulo. |
122 | } type; ///< Multiplication type. |
123 | } mul; ///< For kExprLexMultiplication. |
124 | |
125 | struct { |
126 | bool closing; ///< True if bracket/etc is a closing one. |
127 | } brc; ///< For brackets/braces/parenthesis. |
128 | |
129 | struct { |
130 | int name; ///< Register name, may be -1 if name not present. |
131 | } reg; ///< For kExprLexRegister. |
132 | |
133 | struct { |
134 | bool closed; ///< True if quote was closed. |
135 | } str; ///< For kExprLexSingleQuotedString and kExprLexDoubleQuotedString. |
136 | |
137 | struct { |
138 | const char *name; ///< Option name start. |
139 | size_t len; ///< Option name length. |
140 | ExprOptScope scope; ///< Option scope: &l:, &g: or not specified. |
141 | } opt; ///< Option properties. |
142 | |
143 | struct { |
144 | ExprVarScope scope; ///< Scope character or 0 if not present. |
145 | bool autoload; ///< Has autoload characters. |
146 | } var; ///< For kExprLexPlainIdentifier |
147 | |
148 | struct { |
149 | LexExprTokenType type; ///< Suggested type for parsing incorrect code. |
150 | const char *msg; ///< Error message. |
151 | } err; ///< For kExprLexInvalid |
152 | |
153 | struct { |
154 | union { |
155 | float_T floating; |
156 | uvarnumber_T integer; |
157 | } val; ///< Number value. |
158 | uint8_t base; ///< Base: 2, 8, 10 or 16. |
159 | bool is_float; ///< True if number is a floating-point. |
160 | } num; ///< For kExprLexNumber |
161 | |
162 | struct { |
163 | ExprAssignmentType type; |
164 | } ass; ///< For kExprLexAssignment |
165 | } data; ///< Additional data, if needed. |
166 | } LexExprToken; |
167 | |
168 | typedef enum { |
169 | /// If set, “pointer” to the current byte in pstate will not be shifted |
170 | kELFlagPeek = (1 << 0), |
171 | /// Determines whether scope is allowed to come before the identifier |
172 | kELFlagForbidScope = (1 << 1), |
173 | /// Determines whether floating-point numbers are allowed |
174 | /// |
175 | /// I.e. whether dot is a decimal point separator or is not a part of |
176 | /// a number at all. |
177 | kELFlagAllowFloat = (1 << 2), |
178 | /// Determines whether `is` and `isnot` are seen as comparison operators |
179 | /// |
180 | /// If set they are supposed to be just regular identifiers. |
181 | kELFlagIsNotCmp = (1 << 3), |
182 | /// Determines whether EOC tokens are allowed |
183 | /// |
184 | /// If set then it will yield Invalid token with E15 in place of EOC one if |
185 | /// “EOC” is something like "|". It is fine with emitting EOC at the end of |
186 | /// string still, with or without this flag set. |
187 | kELFlagForbidEOC = (1 << 4), |
188 | // XXX Whenever you add a new flag, alter klee_assume() statement in |
189 | // viml_expressions_lexer.c. |
190 | } LexExprFlags; |
191 | |
192 | /// Expression AST node type |
193 | typedef enum { |
194 | kExprNodeMissing = 0, |
195 | kExprNodeOpMissing, |
196 | kExprNodeTernary, ///< Ternary operator. |
197 | kExprNodeTernaryValue, ///< Ternary operator, colon. |
198 | kExprNodeRegister, ///< Register. |
199 | kExprNodeSubscript, ///< Subscript. |
200 | kExprNodeListLiteral, ///< List literal. |
201 | kExprNodeUnaryPlus, |
202 | kExprNodeBinaryPlus, |
203 | kExprNodeNested, ///< Nested parenthesised expression. |
204 | kExprNodeCall, ///< Function call. |
205 | /// Plain identifier: simple variable/function name |
206 | /// |
207 | /// Looks like "string", "g:Foo", etc: consists from a single |
208 | /// kExprLexPlainIdentifier token. |
209 | kExprNodePlainIdentifier, |
210 | /// Plain dictionary key, for use with kExprNodeConcatOrSubscript |
211 | kExprNodePlainKey, |
212 | /// Complex identifier: variable/function name with curly braces |
213 | kExprNodeComplexIdentifier, |
214 | /// Figure brace expression which is not yet known |
215 | /// |
216 | /// May resolve to any of kExprNodeDictLiteral, kExprNodeLambda or |
217 | /// kExprNodeCurlyBracesIdentifier. |
218 | kExprNodeUnknownFigure, |
219 | kExprNodeLambda, ///< Lambda. |
220 | kExprNodeDictLiteral, ///< Dictionary literal. |
221 | kExprNodeCurlyBracesIdentifier, ///< Part of the curly braces name. |
222 | kExprNodeComma, ///< Comma “operator”. |
223 | kExprNodeColon, ///< Colon “operator”. |
224 | kExprNodeArrow, ///< Arrow “operator”. |
225 | kExprNodeComparison, ///< Various comparison operators. |
226 | /// Concat operator |
227 | /// |
228 | /// To be only used in cases when it is known for sure it is not a subscript. |
229 | kExprNodeConcat, |
230 | /// Concat or subscript operator |
231 | /// |
232 | /// For cases when it is not obvious whether expression is a concat or |
233 | /// a subscript. May only have either number or plain identifier as the second |
234 | /// child. To make it easier to avoid curly braces in place of |
235 | /// kExprNodePlainIdentifier node kExprNodePlainKey is used. |
236 | kExprNodeConcatOrSubscript, |
237 | kExprNodeInteger, ///< Integral number. |
238 | kExprNodeFloat, ///< Floating-point number. |
239 | kExprNodeSingleQuotedString, |
240 | kExprNodeDoubleQuotedString, |
241 | kExprNodeOr, |
242 | kExprNodeAnd, |
243 | kExprNodeUnaryMinus, |
244 | kExprNodeBinaryMinus, |
245 | kExprNodeNot, |
246 | kExprNodeMultiplication, |
247 | kExprNodeDivision, |
248 | kExprNodeMod, |
249 | kExprNodeOption, |
250 | kExprNodeEnvironment, |
251 | kExprNodeAssignment, |
252 | // XXX When modifying this list also modify east_node_type_tab both in parser |
253 | // and in tests, and you most likely will also have to alter list of |
254 | // highlight groups stored in highlight_init_cmdline variable. |
255 | } ExprASTNodeType; |
256 | |
257 | typedef struct expr_ast_node ExprASTNode; |
258 | |
259 | /// Structure representing one AST node |
260 | struct expr_ast_node { |
261 | ExprASTNodeType type; ///< Node type. |
262 | /// Node children: e.g. for 1 + 2 nodes 1 and 2 will be children of +. |
263 | ExprASTNode *children; |
264 | /// Next node: e.g. for 1 + 2 child nodes 1 and 2 are put into a single-linked |
265 | /// list: `(+)->children` references only node 1, node 2 is in |
266 | /// `(+)->children->next`. |
267 | ExprASTNode *next; |
268 | ParserPosition start; |
269 | size_t len; |
270 | union { |
271 | struct { |
272 | int name; ///< Register name, may be -1 if name not present. |
273 | } reg; ///< For kExprNodeRegister. |
274 | struct { |
275 | /// Which nodes UnknownFigure can’t possibly represent. |
276 | struct { |
277 | /// True if UnknownFigure may actually represent dictionary literal. |
278 | bool allow_dict; |
279 | /// True if UnknownFigure may actually represent lambda. |
280 | bool allow_lambda; |
281 | /// True if UnknownFigure may actually be part of curly braces name. |
282 | bool allow_ident; |
283 | } type_guesses; |
284 | /// Highlight chunk index, used for rehighlighting if needed |
285 | size_t opening_hl_idx; |
286 | } fig; ///< For kExprNodeUnknownFigure. |
287 | struct { |
288 | ExprVarScope scope; ///< Scope character or 0 if not present. |
289 | /// Actual identifier without scope. |
290 | /// |
291 | /// Points to inside parser reader state. |
292 | const char *ident; |
293 | size_t ident_len; ///< Actual identifier length. |
294 | } var; ///< For kExprNodePlainIdentifier and kExprNodePlainKey. |
295 | struct { |
296 | bool got_colon; ///< True if colon was seen. |
297 | } ter; ///< For kExprNodeTernaryValue. |
298 | struct { |
299 | ExprComparisonType type; ///< Comparison type. |
300 | ExprCaseCompareStrategy ccs; ///< Case comparison strategy. |
301 | bool inv; ///< True if comparison is to be inverted. |
302 | } cmp; ///< For kExprNodeComparison. |
303 | struct { |
304 | uvarnumber_T value; |
305 | } num; ///< For kExprNodeInteger. |
306 | struct { |
307 | float_T value; |
308 | } flt; ///< For kExprNodeFloat. |
309 | struct { |
310 | char *value; |
311 | size_t size; |
312 | } str; ///< For kExprNodeSingleQuotedString and |
313 | ///< kExprNodeDoubleQuotedString. |
314 | struct { |
315 | const char *ident; ///< Option name start. |
316 | size_t ident_len; ///< Option name length. |
317 | ExprOptScope scope; ///< Option scope: &l:, &g: or not specified. |
318 | } opt; ///< For kExprNodeOption. |
319 | struct { |
320 | const char *ident; ///< Environment variable name start. |
321 | size_t ident_len; ///< Environment variable name length. |
322 | } env; ///< For kExprNodeEnvironment. |
323 | struct { |
324 | ExprAssignmentType type; |
325 | } ass; ///< For kExprNodeAssignment |
326 | } data; |
327 | }; |
328 | |
329 | enum { |
330 | /// Allow multiple expressions in a row: e.g. for :echo |
331 | /// |
332 | /// Parser will still parse only one of them though. |
333 | kExprFlagsMulti = (1 << 0), |
334 | /// Allow NL, NUL and bar to be EOC |
335 | /// |
336 | /// When parsing expressions input by user bar is assumed to be a binary |
337 | /// operator and other two are spacings. |
338 | kExprFlagsDisallowEOC = (1 << 1), |
339 | /// Parse :let argument |
340 | /// |
341 | /// That mean that top level node must be an assignment and first nodes |
342 | /// belong to lvalues. |
343 | kExprFlagsParseLet = (1 << 2), |
344 | // XXX whenever you add a new flag, alter klee_assume() statement in |
345 | // viml_expressions_parser.c, nvim_parse_expression() flags parsing |
346 | // alongside with its documentation and flag sets in check_parsing() |
347 | // function in expressions parser functional and unit tests. |
348 | } ExprParserFlags; |
349 | |
350 | /// AST error definition |
351 | typedef struct { |
352 | /// Error message. Must contain a single printf format atom: %.*s. |
353 | const char *msg; |
354 | /// Error message argument: points to the location of the error. |
355 | const char *arg; |
356 | /// Message argument length: length till the end of string. |
357 | int arg_len; |
358 | } ExprASTError; |
359 | |
360 | /// Structure representing complety AST for one expression |
361 | typedef struct { |
362 | /// When AST is not correct this message will be printed. |
363 | /// |
364 | /// Uses `emsgf(msg, arg_len, arg);`, `msg` is assumed to contain only `%.*s`. |
365 | ExprASTError err; |
366 | /// Root node of the AST. |
367 | ExprASTNode *root; |
368 | } ExprAST; |
369 | |
370 | /// Array mapping ExprASTNodeType to maximum amount of children node may have |
371 | extern const uint8_t node_maxchildren[]; |
372 | |
373 | /// Array mapping ExprASTNodeType values to their stringified versions |
374 | extern const char *const east_node_type_tab[]; |
375 | |
376 | /// Array mapping ExprComparisonType values to their stringified versions |
377 | extern const char *const eltkn_cmp_type_tab[]; |
378 | |
379 | /// Array mapping ExprCaseCompareStrategy values to their stringified versions |
380 | extern const char *const ccs_tab[]; |
381 | |
382 | /// Array mapping ExprAssignmentType values to their stringified versions |
383 | extern const char *const expr_asgn_type_tab[]; |
384 | |
385 | #ifdef INCLUDE_GENERATED_DECLARATIONS |
386 | # include "viml/parser/expressions.h.generated.h" |
387 | #endif |
388 | |
389 | #endif // NVIM_VIML_PARSER_EXPRESSIONS_H |
390 | |