1 #ifndef NVIM_VIML_PARSER_EXPRESSIONS_H
2 #define NVIM_VIML_PARSER_EXPRESSIONS_H
3 
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 
8 #include "nvim/eval/typval.h"
9 #include "nvim/types.h"
10 #include "nvim/viml/parser/parser.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 ExprParserFlags {
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 };
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 `semsg(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