neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

expressions.h (13801B)


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