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
16typedef enum {
17 kCCStrategyUseOption = 0, // 0 for xcalloc
18 kCCStrategyMatchCase = '#',
19 kCCStrategyIgnoreCase = '?',
20} ExprCaseCompareStrategy;
21
22/// Lexer token type
23typedef 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
59typedef 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
68typedef enum {
69 kExprOptScopeUnspecified = 0,
70 kExprOptScopeGlobal = 'g',
71 kExprOptScopeLocal = 'l',
72} ExprOptScope;
73
74/// All possible assignment types: `=` and `{op}=`.
75typedef 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
86typedef 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
106typedef 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
168typedef 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
193typedef 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
257typedef struct expr_ast_node ExprASTNode;
258
259/// Structure representing one AST node
260struct 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
329enum {
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
351typedef 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
361typedef 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
371extern const uint8_t node_maxchildren[];
372
373/// Array mapping ExprASTNodeType values to their stringified versions
374extern const char *const east_node_type_tab[];
375
376/// Array mapping ExprComparisonType values to their stringified versions
377extern const char *const eltkn_cmp_type_tab[];
378
379/// Array mapping ExprCaseCompareStrategy values to their stringified versions
380extern const char *const ccs_tab[];
381
382/// Array mapping ExprAssignmentType values to their stringified versions
383extern 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