#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "nvim/ascii.h"
#include "nvim/charset.h"
#include "nvim/eval/typval.h"
#include "nvim/lib/kvec.h"
#include "nvim/memory.h"
#include "nvim/types.h"
#include "nvim/vim.h"
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
|
#define | VIM_STR2NR(s, ...) vim_str2nr((const char_u *)(s), __VA_ARGS__) |
| VimL expression parser. More...
|
|
#define | GET_CCS(ret, pline) |
|
#define | BRACKET(typ, opning, clsing) |
|
#define | CHAR(typ, ch) |
|
#define | MUL(mul_type, ch) |
|
#define | CHARREG(typ, cond) |
|
#define | ISCTRL(schar) (schar < ' ') |
|
#define | ISWORD_OR_AUTOLOAD(x) (ascii_isident(x) || (x) == AUTOLOAD_CHAR) |
|
#define | OPTNAMEMISS(ret) |
|
#define | CHAR_OR_ASSIGN(ch, ch_type, ass_type) |
|
#define | ADDSTR(...) |
|
#define | TKNARGS(tkn_type, ...) |
|
#define | HL(g) (is_invalid ? "NvimInvalid" #g : "Nvim" #g) |
| Get highlight group name. More...
|
|
#define | HL_CUR_TOKEN(g) |
| Highlight current token with the given group. More...
|
|
#define | NEW_NODE(type) viml_pexpr_new_node(type) |
| Allocate new node, saving some values. More...
|
|
#define | POS_FROM_TOKEN(cur_node, cur_token) |
|
#define | NEW_NODE_WITH_CUR_POS(cur_node, typ) |
|
#define | MAY_HAVE_NEXT_EXPR (kv_size(ast_stack) == 1) |
|
#define | ADD_OP_NODE(cur_node) |
|
#define | OP_MISSING |
|
#define | ADD_VALUE_IF_MISSING(msg) |
|
#define | ERROR_FROM_TOKEN_AND_MSG(cur_token, msg) |
| Set error from the given token and given message. More...
|
|
#define | ERROR_FROM_NODE_AND_MSG(node, msg) |
| Like ERROR_FROM_TOKEN_AND_MSG, but gets position from a node. More...
|
|
#define | ERROR_FROM_TOKEN(cur_token) ERROR_FROM_TOKEN_AND_MSG(cur_token, cur_token.data.err.msg) |
| Set error from the given kExprLexInvalid token. More...
|
|
#define | SELECT_FIGURE_BRACE_TYPE(node, new_type, hl) |
|
#define | ADD_IDENT(new_ident_node_code, hl) |
|
#define | SINGLE_CHAR_ESC(ch, real_ch) |
|
#define | SIMPLE_UB_OP(op) |
|
#define | SIMPLE_B_OP(op, msg) |
|
#define | MUL_OP(lex_op_tail, node_op_tail) |
|
#define | EXP_VAL_COLON "E15: Expected value, got colon: %.*s" |
|
#define | HL_ASGN(asgn, hl) case kExprAsgn##asgn: { HL_CUR_TOKEN(hl); break; } |
|
◆ ADD_IDENT
#define ADD_IDENT |
( |
|
new_ident_node_code, |
|
|
|
hl |
|
) |
| |
Add identifier which should constitute complex identifier node
This one is to be called only in case want_node is kENodeOperator.
- Parameters
-
new_ident_node_code | Code used to create a new identifier node and update want_node and ast_stack, without a trailing semicolon. |
hl | Highlighting name to use, passed as an argument to HL. |
◆ ADD_OP_NODE
#define ADD_OP_NODE |
( |
|
cur_node | ) |
|
Value: is_invalid |= !viml_pexpr_handle_bop(pstate, &ast_stack, cur_node, \
&want_node, &ast.err)
Add operator node
- Parameters
-
◆ ADD_VALUE_IF_MISSING
#define ADD_VALUE_IF_MISSING |
( |
|
msg | ) |
|
Value: do { \
if (want_node == kENodeValue) { \
ERROR_FROM_TOKEN_AND_MSG(cur_token, (
msg)); \
(*top_node_p)->len = 0; \
want_node = kENodeOperator; \
} \
} while (0)
Record missing value: for things like "* 5"
- Parameters
-
◆ ADDSTR
Value: do { \
goto viml_pexpr_repr_token_end; \
} \
} while (0)
◆ BRACKET
#define BRACKET |
( |
|
typ, |
|
|
|
opning, |
|
|
|
clsing |
|
) |
| |
Value: case opning: \
case clsing: { \
ret.type = typ; \
ret.data.brc.closing = (schar == clsing); \
break; \
}
◆ CHAR
Value: case ch: { \
ret.type = typ; \
break; \
}
◆ CHAR_OR_ASSIGN
#define CHAR_OR_ASSIGN |
( |
|
ch, |
|
|
|
ch_type, |
|
|
|
ass_type |
|
) |
| |
Value: case ch: { \
if (pline.size > 1 && pline.data[1] == '=') { \
ret.len++; \
ret.data.ass.type = ass_type; \
} else { \
ret.type = ch_type; \
} \
break; \
}
◆ CHARREG
#define CHARREG |
( |
|
typ, |
|
|
|
cond |
|
) |
| |
Value: do { \
ret.type = typ; \
for (; (
ret.len < pline.size \
&& cond(pline.data[
ret.len])) \
} \
} while (0)
◆ ERROR_FROM_NODE_AND_MSG
#define ERROR_FROM_NODE_AND_MSG |
( |
|
node, |
|
|
|
msg |
|
) |
| |
Value: do { \
is_invalid = true; \
east_set_error(pstate, &ast.err,
msg, node->start); \
} while (0)
Like ERROR_FROM_TOKEN_AND_MSG, but gets position from a node.
◆ ERROR_FROM_TOKEN
Set error from the given kExprLexInvalid token.
◆ ERROR_FROM_TOKEN_AND_MSG
#define ERROR_FROM_TOKEN_AND_MSG |
( |
|
cur_token, |
|
|
|
msg |
|
) |
| |
Value: do { \
is_invalid = true; \
east_set_error(pstate, &ast.err,
msg, cur_token.start); \
} while (0)
Set error from the given token and given message.
◆ EXP_VAL_COLON
#define EXP_VAL_COLON "E15: Expected value, got colon: %.*s" |
◆ GET_CCS
#define GET_CCS |
( |
|
ret, |
|
|
|
pline |
|
) |
| |
Value: do { \
if (
ret.len < pline.size \
&& strchr(
"?#", pline.data[
ret.len]) !=
NULL) { \
ret.data.cmp.ccs = \
} else { \
} \
} while (0)
◆ HL
#define HL |
( |
|
g | ) |
(is_invalid ? "NvimInvalid" #g : "Nvim" #g) |
Get highlight group name.
◆ HL_ASGN
#define HL_ASGN |
( |
|
asgn, |
|
|
|
hl |
|
) |
| case kExprAsgn##asgn: { HL_CUR_TOKEN(hl); break; } |
◆ HL_CUR_TOKEN
#define HL_CUR_TOKEN |
( |
|
g | ) |
|
Value: viml_parser_highlight(pstate, cur_token.start, cur_token.len, \
Highlight current token with the given group.
◆ ISCTRL
#define ISCTRL |
( |
|
schar | ) |
(schar < ' ') |
◆ ISWORD_OR_AUTOLOAD
#define ISWORD_OR_AUTOLOAD |
( |
|
x | ) |
(ascii_isident(x) || (x) == AUTOLOAD_CHAR) |
◆ MAY_HAVE_NEXT_EXPR
#define MAY_HAVE_NEXT_EXPR (kv_size(ast_stack) == 1) |
Check whether it is possible to have next expression after current
For :echo: :echo @a @a
is a valid expression. :echo (@a @a)
is not.
◆ MUL
#define MUL |
( |
|
mul_type, |
|
|
|
ch |
|
) |
| |
Value: case ch: { \
ret.data.mul.type = mul_type; \
break; \
}
◆ MUL_OP
#define MUL_OP |
( |
|
lex_op_tail, |
|
|
|
node_op_tail |
|
) |
| |
Value: case kExprLexMul##lex_op_tail: { \
NEW_NODE_WITH_CUR_POS(cur_node, kExprNode##node_op_tail); \
HL_CUR_TOKEN(node_op_tail); \
break; \
}
◆ NEW_NODE
#define NEW_NODE |
( |
|
type | ) |
viml_pexpr_new_node(type) |
Allocate new node, saving some values.
◆ NEW_NODE_WITH_CUR_POS
#define NEW_NODE_WITH_CUR_POS |
( |
|
cur_node, |
|
|
|
typ |
|
) |
| |
Value: do { \
POS_FROM_TOKEN((cur_node), cur_token); \
(cur_node)->start = prev_token.start; \
(cur_node)->len += prev_token.len; \
} \
} while (0)
Allocate new node and set its position from the current token
If previous token happened to contain spacing then it will be included.
- Parameters
-
cur_node | Variable to save allocated node to. |
typ | Node type. |
◆ OP_MISSING
Value: do { \
\
\
goto viml_pexpr_parse_end; \
} else { \
assert(*top_node_p !=
NULL); \
ERROR_FROM_TOKEN_AND_MSG(cur_token,
_(
"E15: Missing operator: %.*s")); \
cur_node->len = 0; \
ADD_OP_NODE(cur_node); \
goto viml_pexpr_parse_process_token; \
} \
} while (0)
Record missing operator: for things like
:echo @a @a
(allowed) or
:echo (@a @a)
(parsed as OpMissing(, )).
◆ OPTNAMEMISS
#define OPTNAMEMISS |
( |
|
ret | ) |
|
Value: do { \
ret.data.err.msg =
_(
"E112: Option name missing: %.*s"); \
} while (0)
◆ POS_FROM_TOKEN
#define POS_FROM_TOKEN |
( |
|
cur_node, |
|
|
|
cur_token |
|
) |
| |
Value: do { \
(cur_node)->start = cur_token.start; \
(cur_node)->len = cur_token.len; \
} while (0)
Set position of the given node to position from the given token
- Parameters
-
cur_node | Node to modify. |
cur_token | Token to set position from. |
◆ SELECT_FIGURE_BRACE_TYPE
#define SELECT_FIGURE_BRACE_TYPE |
( |
|
node, |
|
|
|
new_type, |
|
|
|
hl |
|
) |
| |
Value: do { \
ExprASTNode *const node_ = (node); \
|| node_->type == kExprNode##new_type); \
node_->type = kExprNode##new_type; \
if (pstate->colors) { \
kv_A(*pstate->colors, node_->data.fig.opening_hl_idx).group = \
HL(hl); \
} \
} while (0)
Select figure brace type, altering highlighting as well if needed
- Parameters
-
[out] | node | Node to modify type. |
[in] | new_type | New type, one of ExprASTNodeType values without kExprNode prefix. |
[in] | hl | Corresponding highlighting, passed as an argument to HL. |
◆ SIMPLE_B_OP
#define SIMPLE_B_OP |
( |
|
op, |
|
|
|
msg |
|
) |
| |
Value: case kExprLex##op: { \
ADD_VALUE_IF_MISSING(
_(
"E15: Unexpected " msg ": %.*s")); \
NEW_NODE_WITH_CUR_POS(cur_node, kExprNode##op); \
HL_CUR_TOKEN(op); \
ADD_OP_NODE(cur_node); \
break; \
}
◆ SIMPLE_UB_OP
#define SIMPLE_UB_OP |
( |
|
op | ) |
|
Value: case kExprLex##op: { \
if (want_node == kENodeValue) { \
\
NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeUnary##op); \
*top_node_p = cur_node; \
kvi_push(ast_stack, &cur_node->children); \
HL_CUR_TOKEN(Unary##op); \
} else { \
NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeBinary##op); \
ADD_OP_NODE(cur_node); \
HL_CUR_TOKEN(Binary##op); \
} \
want_node = kENodeValue; \
break; \
}
◆ SINGLE_CHAR_ESC
#define SINGLE_CHAR_ESC |
( |
|
ch, |
|
|
|
real_ch |
|
) |
| |
Value: case ch: { \
*v_p++ = real_ch; \
p++; \
break; \
}
◆ TKNARGS
#define TKNARGS |
( |
|
tkn_type, |
|
|
|
... |
|
) |
| |
Value: case tkn_type: { \
ADDSTR(__VA_ARGS__); \
break; \
}
◆ VIM_STR2NR
◆ ExprASTParseType
Parse type: what is being parsed currently.
Enumerator |
---|
kEPTExpr | Parsing regular VimL expression.
|
kEPTLambdaArguments | Parsing lambda arguments
Just like parsing function arguments, but it is valid to be ended with an arrow only.
|
kEPTAssignment | Assignment: parsing for :let.
|
kEPTSingleAssignment | Single assignment: used when lists are not allowed (i.e. when nesting)
|
◆ ExprOpAssociativity
Operator associativity.
Enumerator |
---|
kEOpAssNo | Not associative / not applicable.
|
kEOpAssLeft | Left associativity.
|
kEOpAssRight | Right associativity.
|
◆ kvec_withinit_t() [1/2]
Which nodes may be wanted.
Operators: function call, subscripts, binary operators, …
For unrestricted expressions.
Values: literals, variables, nested expressions, unary operators.
For unrestricted expressions as well, implies that top item in AST stack points to NULL.
◆ kvec_withinit_t() [2/2]
Operator priority level.
< Addition, subtraction and concatenation.
< Multiplication, division and modulo.
< Unary operations: not, minus, plus.
< Subscripts.
< Values: literals, variables, nested expressions, …
◆ viml_pexpr_free_ast()
Free memory occupied by AST
- Parameters
-
◆ viml_pexpr_next_token()
Get next token for the VimL expression input
- Parameters
-
| pstate | Parser state. |
[in] | flags | Flags, |
- See also
- LexExprFlags.
- Returns
- Next token.
◆ viml_pexpr_parse()
Parse one VimL expression
- Parameters
-
| pstate | Parser state. |
[in] | flags | Additional flags, see ExprParserFlags |
- Returns
- Parsed AST.
◆ viml_pexpr_repr_token()
const char* viml_pexpr_repr_token |
( |
const ParserState *const |
pstate, |
|
|
const LexExprToken |
token, |
|
|
size_t *const |
ret_size |
|
) |
| |
Represent token as a string
Intended for testing and debugging purposes.
- Parameters
-
[in] | pstate | Parser state, needed to get token string from it. May be NULL, in which case in place of obtaining part of the string represented by token only token length is returned. |
[in] | token | Token to represent. |
[out] | ret_size | Return string size, for cases like NULs inside a string. May be NULL. |
- Returns
- Token represented in a string form, in a static buffer (overwritten on each call).
◆ ass
◆ ccs_tab
const char* const ccs_tab[] |
Initial value:
Array mapping ExprCaseCompareStrategy values to their stringified versions.
◆ east_node_type_tab
const char* const east_node_type_tab[] |
Array mapping ExprASTNodeType values to their stringified versions.
◆ eltkn_cmp_type_tab
const char* const eltkn_cmp_type_tab[] |
Initial value:
Array mapping ExprComparisonType values to their stringified versions.
◆ expr_asgn_type_tab
const char* const expr_asgn_type_tab[] |
Initial value:
Array mapping ExprAssignmentType values to their stringified versions.
◆ ExprASTWantedNode
◆ ExprOpLvl
◆ lvl
◆ node_maxchildren
const uint8_t node_maxchildren[] |
Array mapping ExprASTNodeType to maximum amount of children node may have.
#define _(x)
Definition: gettext.h:20
#define MAY_HAVE_NEXT_EXPR
Definition: expressions.c:1410
char * p
Definition: eval.c:2017
ExprCaseCompareStrategy
Definition: expressions.h:16
@ kExprLexAssignment
Assignment: = or {op}=.
Definition: expressions.h:54
@ kExprCmpEqual
Equality, inequality.
Definition: expressions.h:60
@ kExprFlagsMulti
Definition: expressions.h:333
@ kExprLexSpacing
Spaces, tabs, newlines, etc.
Definition: expressions.h:26
const int ret
Definition: eval.c:746
@ kCCStrategyIgnoreCase
Definition: expressions.h:19
@ kExprAsgnAdd
Assignment augmented with addition: +=.
Definition: expressions.h:77
@ kExprCmpGreaterOrEqual
>= or <.
Definition: expressions.h:63
@ kCCStrategyMatchCase
Definition: expressions.h:18
@ kExprCmpGreater
> or <=
Definition: expressions.h:62
@ kExprCmpMatches
Matches regex, not matches regex.
Definition: expressions.h:61
@ kExprCmpIdentical
is or isnot
Definition: expressions.h:64
@ kExprAsgnConcat
Assignment augmented with concatenation: .=.
Definition: expressions.h:79
err msg
Definition: helpers.c:1110
@ kExprLexOption
&optionname option value.
Definition: expressions.h:44
@ kExprNodeMissing
Definition: expressions.h:194
#define HL(g)
Get highlight group name.
Definition: expressions.c:1370
@ kExprAsgnPlain
Plain assignment: =.
Definition: expressions.h:76
@ kExprAsgnSubtract
Assignment augmented with subtraction: -=.
Definition: expressions.h:78
@ kExprNodeOpMissing
Definition: expressions.h:195
snprintf((char *) pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat)
@ kExprLexMultiplication
Multiplication, division or modulo operator.
Definition: expressions.h:37
@ kExprLexInvalid
Invalid token, indicaten an error.
Definition: expressions.h:24
@ kCCStrategyUseOption
Definition: expressions.h:17
return NULL
Definition: eval.c:9968
#define NEW_NODE(type)
Allocate new node, saving some values.
Definition: expressions.c:1378
@ kExprNodeUnknownFigure
Definition: expressions.h:218