aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/viml/parser
diff options
context:
space:
mode:
authordundargoc <33953936+dundargoc@users.noreply.github.com>2021-09-18 18:34:23 +0200
committerGitHub <noreply@github.com>2021-09-18 09:34:23 -0700
commit51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6 (patch)
treeb0a582d67883864eda3231bce45dc7c159cbe97f /src/nvim/viml/parser
parent6cad86fffdb91d3997a707ff6adb0b5991587b3e (diff)
downloadrneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.tar.gz
rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.tar.bz2
rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.zip
refactor: format #15702
Diffstat (limited to 'src/nvim/viml/parser')
-rw-r--r--src/nvim/viml/parser/expressions.c3267
1 files changed, 1623 insertions, 1644 deletions
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 967d656dc5..c2aa923c49 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -50,20 +50,19 @@
// 7. 'isident' no longer applies to environment variables, they always include
// ASCII alphanumeric characters and underscore and nothing except this.
+#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
-#include <assert.h>
#include <string.h>
-#include "nvim/vim.h"
-#include "nvim/memory.h"
-#include "nvim/types.h"
-#include "nvim/charset.h"
#include "nvim/ascii.h"
#include "nvim/assert.h"
-#include "nvim/lib/kvec.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"
@@ -143,10 +142,8 @@ typedef enum {
/// numbers are not supported.
/// @param[in] exponent Exponent to scale by.
/// @param[in] exponent_negative True if exponent is negative.
-static inline float_T scale_number(const float_T num,
- const uint8_t base,
- const uvarnumber_T exponent,
- const bool exponent_negative)
+static inline float_T scale_number(const float_T num, const uint8_t base,
+ const uvarnumber_T exponent, const bool exponent_negative)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
{
if (num == 0 || exponent == 0) {
@@ -200,7 +197,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
if (ret.len < pline.size \
&& strchr("?#", pline.data[ret.len]) != NULL) { \
ret.data.cmp.ccs = \
- (ExprCaseCompareStrategy)pline.data[ret.len]; \
+ (ExprCaseCompareStrategy)pline.data[ret.len]; \
ret.len++; \
} else { \
ret.data.cmp.ccs = kCCStrategyUseOption; \
@@ -209,12 +206,12 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
switch (schar) {
// Paired brackets.
#define BRACKET(typ, opning, clsing) \
- case opning: \
- case clsing: { \
- ret.type = typ; \
- ret.data.brc.closing = (schar == clsing); \
- break; \
- }
+case opning: \
+case clsing: { \
+ ret.type = typ; \
+ ret.data.brc.closing = (schar == clsing); \
+ break; \
+}
BRACKET(kExprLexParenthesis, '(', ')')
BRACKET(kExprLexBracket, '[', ']')
BRACKET(kExprLexFigureBrace, '{', '}')
@@ -222,10 +219,10 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
// Single character tokens without data.
#define CHAR(typ, ch) \
- case ch: { \
- ret.type = typ; \
- break; \
- }
+case ch: { \
+ ret.type = typ; \
+ break; \
+}
CHAR(kExprLexQuestion, '?')
CHAR(kExprLexColon, ':')
CHAR(kExprLexComma, ',')
@@ -233,198 +230,265 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
// Multiplication/division/modulo.
#define MUL(mul_type, ch) \
- case ch: { \
- ret.type = kExprLexMultiplication; \
- ret.data.mul.type = mul_type; \
- break; \
- }
+case ch: { \
+ ret.type = kExprLexMultiplication; \
+ ret.data.mul.type = mul_type; \
+ break; \
+}
MUL(kExprLexMulMul, '*')
MUL(kExprLexMulDiv, '/')
MUL(kExprLexMulMod, '%')
#undef MUL
#define CHARREG(typ, cond) \
- do { \
- ret.type = typ; \
- for (; (ret.len < pline.size \
- && cond(pline.data[ret.len])) \
- ; ret.len++) { \
- } \
- } while (0)
-
- // Whitespace.
- case ' ':
- case TAB: {
- CHARREG(kExprLexSpacing, ascii_iswhite);
- break;
- }
-
- // Control character, except for NUL, NL and TAB.
- case Ctrl_A: case Ctrl_B: case Ctrl_C: case Ctrl_D: case Ctrl_E:
- case Ctrl_F: case Ctrl_G: case Ctrl_H:
+ do { \
+ ret.type = typ; \
+ for (; (ret.len < pline.size \
+ && cond(pline.data[ret.len])) \
+ ; ret.len++) { \
+ } \
+ } while (0)
- case Ctrl_K: case Ctrl_L: case Ctrl_M: case Ctrl_N: case Ctrl_O:
- case Ctrl_P: case Ctrl_Q: case Ctrl_R: case Ctrl_S: case Ctrl_T:
- case Ctrl_U: case Ctrl_V: case Ctrl_W: case Ctrl_X: case Ctrl_Y:
- case Ctrl_Z: {
+ // Whitespace.
+ case ' ':
+ case TAB:
+ CHARREG(kExprLexSpacing, ascii_iswhite);
+ break;
+
+ // Control character, except for NUL, NL and TAB.
+ case Ctrl_A:
+ case Ctrl_B:
+ case Ctrl_C:
+ case Ctrl_D:
+ case Ctrl_E:
+ case Ctrl_F:
+ case Ctrl_G:
+ case Ctrl_H:
+
+ case Ctrl_K:
+ case Ctrl_L:
+ case Ctrl_M:
+ case Ctrl_N:
+ case Ctrl_O:
+ case Ctrl_P:
+ case Ctrl_Q:
+ case Ctrl_R:
+ case Ctrl_S:
+ case Ctrl_T:
+ case Ctrl_U:
+ case Ctrl_V:
+ case Ctrl_W:
+ case Ctrl_X:
+ case Ctrl_Y:
+ case Ctrl_Z:
#define ISCTRL(schar) (schar < ' ')
- CHARREG(kExprLexInvalid, ISCTRL);
- ret.data.err.type = kExprLexSpacing;
- ret.data.err.msg =
- _("E15: Invalid control character present in input: %.*s");
- break;
+ CHARREG(kExprLexInvalid, ISCTRL);
+ ret.data.err.type = kExprLexSpacing;
+ ret.data.err.msg =
+ _("E15: Invalid control character present in input: %.*s");
+ break;
#undef ISCTRL
- }
- // Number.
- case '0': case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9': {
- ret.data.num.is_float = false;
- ret.data.num.base = 10;
- size_t frac_start = 0;
- size_t exp_start = 0;
- size_t frac_end = 0;
- bool exp_negative = false;
- CHARREG(kExprLexNumber, ascii_isdigit);
- if (flags & kELFlagAllowFloat) {
- const LexExprToken non_float_ret = ret;
+ // Number.
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ ret.data.num.is_float = false;
+ ret.data.num.base = 10;
+ size_t frac_start = 0;
+ size_t exp_start = 0;
+ size_t frac_end = 0;
+ bool exp_negative = false;
+ CHARREG(kExprLexNumber, ascii_isdigit);
+ if (flags & kELFlagAllowFloat) {
+ const LexExprToken non_float_ret = ret;
+ if (pline.size > ret.len + 1
+ && pline.data[ret.len] == '.'
+ && ascii_isdigit(pline.data[ret.len + 1])) {
+ ret.len++;
+ frac_start = ret.len;
+ frac_end = ret.len;
+ ret.data.num.is_float = true;
+ for (; ret.len < pline.size && ascii_isdigit(pline.data[ret.len])
+ ; ret.len++) {
+ // A small optimization: trailing zeroes in fractional part do not
+ // add anything to significand, so it is useless to include them in
+ // frac_end.
+ if (pline.data[ret.len] != '0') {
+ frac_end = ret.len + 1;
+ }
+ }
if (pline.size > ret.len + 1
- && pline.data[ret.len] == '.'
- && ascii_isdigit(pline.data[ret.len + 1])) {
+ && (pline.data[ret.len] == 'e'
+ || pline.data[ret.len] == 'E')
+ && ((pline.size > ret.len + 2
+ && (pline.data[ret.len + 1] == '+'
+ || pline.data[ret.len + 1] == '-')
+ && ascii_isdigit(pline.data[ret.len + 2]))
+ || ascii_isdigit(pline.data[ret.len + 1]))) {
ret.len++;
- frac_start = ret.len;
- frac_end = ret.len;
- ret.data.num.is_float = true;
- for (; ret.len < pline.size && ascii_isdigit(pline.data[ret.len])
- ; ret.len++) {
- // A small optimization: trailing zeroes in fractional part do not
- // add anything to significand, so it is useless to include them in
- // frac_end.
- if (pline.data[ret.len] != '0') {
- frac_end = ret.len + 1;
- }
- }
- if (pline.size > ret.len + 1
- && (pline.data[ret.len] == 'e'
- || pline.data[ret.len] == 'E')
- && ((pline.size > ret.len + 2
- && (pline.data[ret.len + 1] == '+'
- || pline.data[ret.len + 1] == '-')
- && ascii_isdigit(pline.data[ret.len + 2]))
- || ascii_isdigit(pline.data[ret.len + 1]))) {
+ if (pline.data[ret.len] == '+'
+ || (exp_negative = (pline.data[ret.len] == '-'))) {
ret.len++;
- if (pline.data[ret.len] == '+'
- || (exp_negative = (pline.data[ret.len] == '-'))) {
- ret.len++;
- }
- exp_start = ret.len;
- CHARREG(kExprLexNumber, ascii_isdigit);
}
- }
- if (pline.size > ret.len
- && (pline.data[ret.len] == '.'
- || ASCII_ISALPHA(pline.data[ret.len]))) {
- ret = non_float_ret;
+ exp_start = ret.len;
+ CHARREG(kExprLexNumber, ascii_isdigit);
}
}
- // TODO(ZyX-I): detect overflows
- if (ret.data.num.is_float) {
- // Vim used to use string2float here which in turn uses strtod(). There
- // are two problems with this approach:
- // 1. strtod() is locale-dependent. Not sure how it is worked around so
- // that I do not see relevant bugs, but it still does not look like
- // a good idea.
- // 2. strtod() does not accept length argument.
- //
- // The below variant of parsing floats was recognized as acceptable
- // because it is basically how uClibc does the thing: it generates
- // a number ignoring decimal point (but recording its position), then
- // uses recorded position to scale number down when processing exponent.
- float_T significand_part = 0;
- uvarnumber_T exp_part = 0;
- const size_t frac_size = (size_t)(frac_end - frac_start);
- for (size_t i = 0; i < frac_end; i++) {
- if (i == frac_start - 1) {
- continue;
- }
- significand_part = significand_part * 10 + (pline.data[i] - '0');
- }
- if (exp_start) {
- vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part,
- (int)(ret.len - exp_start), false);
+ if (pline.size > ret.len
+ && (pline.data[ret.len] == '.'
+ || ASCII_ISALPHA(pline.data[ret.len]))) {
+ ret = non_float_ret;
+ }
+ }
+ // TODO(ZyX-I): detect overflows
+ if (ret.data.num.is_float) {
+ // Vim used to use string2float here which in turn uses strtod(). There
+ // are two problems with this approach:
+ // 1. strtod() is locale-dependent. Not sure how it is worked around so
+ // that I do not see relevant bugs, but it still does not look like
+ // a good idea.
+ // 2. strtod() does not accept length argument.
+ //
+ // The below variant of parsing floats was recognized as acceptable
+ // because it is basically how uClibc does the thing: it generates
+ // a number ignoring decimal point (but recording its position), then
+ // uses recorded position to scale number down when processing exponent.
+ float_T significand_part = 0;
+ uvarnumber_T exp_part = 0;
+ const size_t frac_size = (size_t)(frac_end - frac_start);
+ for (size_t i = 0; i < frac_end; i++) {
+ if (i == frac_start - 1) {
+ continue;
}
- if (exp_negative) {
- exp_part += frac_size;
+ significand_part = significand_part * 10 + (pline.data[i] - '0');
+ }
+ if (exp_start) {
+ vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part,
+ (int)(ret.len - exp_start), false);
+ }
+ if (exp_negative) {
+ exp_part += frac_size;
+ } else {
+ if (exp_part < frac_size) {
+ exp_negative = true;
+ exp_part = frac_size - exp_part;
} else {
- if (exp_part < frac_size) {
- exp_negative = true;
- exp_part = frac_size - exp_part;
- } else {
- exp_part -= frac_size;
- }
+ exp_part -= frac_size;
}
- ret.data.num.val.floating = scale_number(significand_part, 10, exp_part,
- exp_negative);
- } else {
- int len;
- int prep;
- vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL,
- &ret.data.num.val.integer, (int)pline.size, false);
- ret.len = (size_t)len;
- const uint8_t bases[] = {
- [0] = 10,
- ['0'] = 8,
- ['x'] = 16, ['X'] = 16,
- ['b'] = 2, ['B'] = 2,
- };
- ret.data.num.base = bases[prep];
}
- break;
+ ret.data.num.val.floating = scale_number(significand_part, 10, exp_part,
+ exp_negative);
+ } else {
+ int len;
+ int prep;
+ vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL,
+ &ret.data.num.val.integer, (int)pline.size, false);
+ ret.len = (size_t)len;
+ const uint8_t bases[] = {
+ [0] = 10,
+ ['0'] = 8,
+ ['x'] = 16, ['X'] = 16,
+ ['b'] = 2, ['B'] = 2,
+ };
+ ret.data.num.base = bases[prep];
}
+ break;
+ }
#define ISWORD_OR_AUTOLOAD(x) \
- (ascii_isident(x) || (x) == AUTOLOAD_CHAR)
-
- // Environment variable.
- case '$': {
- CHARREG(kExprLexEnv, ascii_isident);
- break;
- }
-
- // Normal variable/function name.
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
- case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
- case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
- case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
- case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
- case 'V': case 'W': case 'X': case 'Y': case 'Z':
- case '_': {
- ret.data.var.scope = 0;
- ret.data.var.autoload = false;
- CHARREG(kExprLexPlainIdentifier, ascii_isident);
- // "is" and "isnot" operators.
- if (!(flags & kELFlagIsNotCmp)
- && ((ret.len == 2 && memcmp(pline.data, "is", 2) == 0)
- || (ret.len == 5 && memcmp(pline.data, "isnot", 5) == 0))) {
- ret.type = kExprLexComparison;
- ret.data.cmp.type = kExprCmpIdentical;
- ret.data.cmp.inv = (ret.len == 5);
- GET_CCS(ret, pline);
+ (ascii_isident(x) || (x) == AUTOLOAD_CHAR)
+
+ // Environment variable.
+ case '$':
+ CHARREG(kExprLexEnv, ascii_isident);
+ break;
+
+ // Normal variable/function name.
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ ret.data.var.scope = 0;
+ ret.data.var.autoload = false;
+ CHARREG(kExprLexPlainIdentifier, ascii_isident);
+ // "is" and "isnot" operators.
+ if (!(flags & kELFlagIsNotCmp)
+ && ((ret.len == 2 && memcmp(pline.data, "is", 2) == 0)
+ || (ret.len == 5 && memcmp(pline.data, "isnot", 5) == 0))) {
+ ret.type = kExprLexComparison;
+ ret.data.cmp.type = kExprCmpIdentical;
+ ret.data.cmp.inv = (ret.len == 5);
+ GET_CCS(ret, pline);
// Scope: `s:`, etc.
- } else if (ret.len == 1
- && pline.size > 1
- && memchr(EXPR_VAR_SCOPE_LIST, schar,
- sizeof(EXPR_VAR_SCOPE_LIST)) != NULL
- && pline.data[ret.len] == ':'
- && !(flags & kELFlagForbidScope)) {
- ret.len++;
- ret.data.var.scope = (ExprVarScope)schar;
- CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD);
- ret.data.var.autoload = (
- memchr(pline.data + 2, AUTOLOAD_CHAR, ret.len - 2)
- != NULL);
+ } else if (ret.len == 1
+ && pline.size > 1
+ && memchr(EXPR_VAR_SCOPE_LIST, schar,
+ sizeof(EXPR_VAR_SCOPE_LIST)) != NULL
+ && pline.data[ret.len] == ':'
+ && !(flags & kELFlagForbidScope)) {
+ ret.len++;
+ ret.data.var.scope = (ExprVarScope)schar;
+ CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD);
+ ret.data.var.autoload = (
+ memchr(pline.data + 2, AUTOLOAD_CHAR, ret.len - 2)
+ != NULL);
// Previous CHARREG stopped at autoload character in order to make it
// possible to detect `is#`. Continue now with autoload characters
// included.
@@ -432,221 +496,213 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
// Warning: there is ambiguity for the lexer: `is#Foo(1)` is a call of
// function `is#Foo()`, `1is#Foo(1)` is a comparison `1 is# Foo(1)`. This
// needs to be resolved on the higher level where context is available.
- } else if (pline.size > ret.len
- && pline.data[ret.len] == AUTOLOAD_CHAR) {
- ret.data.var.autoload = true;
- CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD);
- }
- break;
+ } else if (pline.size > ret.len
+ && pline.data[ret.len] == AUTOLOAD_CHAR) {
+ ret.data.var.autoload = true;
+ CHARREG(kExprLexPlainIdentifier, ISWORD_OR_AUTOLOAD);
}
+ break;
#undef ISWORD_OR_AUTOLOAD
#undef CHARREG
- // Option.
- case '&': {
+ // Option.
+ case '&': {
#define OPTNAMEMISS(ret) \
- do { \
- ret.type = kExprLexInvalid; \
- ret.data.err.type = kExprLexOption; \
- ret.data.err.msg = _("E112: Option name missing: %.*s"); \
- } while (0)
- if (pline.size > 1 && pline.data[1] == '&') {
- ret.type = kExprLexAnd;
- ret.len++;
- break;
+ do { \
+ ret.type = kExprLexInvalid; \
+ ret.data.err.type = kExprLexOption; \
+ ret.data.err.msg = _("E112: Option name missing: %.*s"); \
+ } while (0)
+ if (pline.size > 1 && pline.data[1] == '&') {
+ ret.type = kExprLexAnd;
+ ret.len++;
+ break;
+ }
+ if (pline.size == 1 || !ASCII_ISALPHA(pline.data[1])) {
+ OPTNAMEMISS(ret);
+ break;
+ }
+ ret.type = kExprLexOption;
+ if (pline.size > 2
+ && pline.data[2] == ':'
+ && memchr(EXPR_OPT_SCOPE_LIST, pline.data[1],
+ sizeof(EXPR_OPT_SCOPE_LIST)) != NULL) {
+ ret.len += 2;
+ ret.data.opt.scope = (ExprOptScope)pline.data[1];
+ ret.data.opt.name = pline.data + 3;
+ } else {
+ ret.data.opt.scope = kExprOptScopeUnspecified;
+ ret.data.opt.name = pline.data + 1;
+ }
+ const char *p = ret.data.opt.name;
+ const char *const e = pline.data + pline.size;
+ if (e - p >= 4 && p[0] == 't' && p[1] == '_') {
+ ret.data.opt.len = 4;
+ ret.len += 4;
+ } else {
+ for (; p < e && ASCII_ISALPHA(*p); p++) {
}
- if (pline.size == 1 || !ASCII_ISALPHA(pline.data[1])) {
+ ret.data.opt.len = (size_t)(p - ret.data.opt.name);
+ if (ret.data.opt.len == 0) {
OPTNAMEMISS(ret);
- break;
- }
- ret.type = kExprLexOption;
- if (pline.size > 2
- && pline.data[2] == ':'
- && memchr(EXPR_OPT_SCOPE_LIST, pline.data[1],
- sizeof(EXPR_OPT_SCOPE_LIST)) != NULL) {
- ret.len += 2;
- ret.data.opt.scope = (ExprOptScope)pline.data[1];
- ret.data.opt.name = pline.data + 3;
} else {
- ret.data.opt.scope = kExprOptScopeUnspecified;
- ret.data.opt.name = pline.data + 1;
- }
- const char *p = ret.data.opt.name;
- const char *const e = pline.data + pline.size;
- if (e - p >= 4 && p[0] == 't' && p[1] == '_') {
- ret.data.opt.len = 4;
- ret.len += 4;
- } else {
- for (; p < e && ASCII_ISALPHA(*p); p++) {
- }
- ret.data.opt.len = (size_t)(p - ret.data.opt.name);
- if (ret.data.opt.len == 0) {
- OPTNAMEMISS(ret);
- } else {
- ret.len += ret.data.opt.len;
- }
+ ret.len += ret.data.opt.len;
}
- break;
-#undef OPTNAMEMISS
}
+ break;
+#undef OPTNAMEMISS
+ }
- // Register.
- case '@': {
- ret.type = kExprLexRegister;
- if (pline.size > 1) {
- ret.len++;
- ret.data.reg.name = (uint8_t)pline.data[1];
- } else {
- ret.data.reg.name = -1;
- }
- break;
+ // Register.
+ case '@':
+ ret.type = kExprLexRegister;
+ if (pline.size > 1) {
+ ret.len++;
+ ret.data.reg.name = (uint8_t)pline.data[1];
+ } else {
+ ret.data.reg.name = -1;
}
-
- // Single quoted string.
- case '\'': {
- ret.type = kExprLexSingleQuotedString;
- ret.data.str.closed = false;
- for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) {
- if (pline.data[ret.len] == '\'') {
- if (ret.len + 1 < pline.size && pline.data[ret.len + 1] == '\'') {
- ret.len++;
- } else {
- ret.data.str.closed = true;
- }
+ break;
+
+ // Single quoted string.
+ case '\'':
+ ret.type = kExprLexSingleQuotedString;
+ ret.data.str.closed = false;
+ for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) {
+ if (pline.data[ret.len] == '\'') {
+ if (ret.len + 1 < pline.size && pline.data[ret.len + 1] == '\'') {
+ ret.len++;
+ } else {
+ ret.data.str.closed = true;
}
}
- break;
}
-
- // Double quoted string.
- case '"': {
- ret.type = kExprLexDoubleQuotedString;
- ret.data.str.closed = false;
- for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) {
- if (pline.data[ret.len] == '\\') {
- if (ret.len + 1 < pline.size) {
- ret.len++;
- }
- } else if (pline.data[ret.len] == '"') {
- ret.data.str.closed = true;
+ break;
+
+ // Double quoted string.
+ case '"':
+ ret.type = kExprLexDoubleQuotedString;
+ ret.data.str.closed = false;
+ for (; ret.len < pline.size && !ret.data.str.closed; ret.len++) {
+ if (pline.data[ret.len] == '\\') {
+ if (ret.len + 1 < pline.size) {
+ ret.len++;
}
+ } else if (pline.data[ret.len] == '"') {
+ ret.data.str.closed = true;
}
- break;
}
-
- // Unary not, (un)equality and regex (not) match comparison operators.
- case '!':
- case '=': {
- if (pline.size == 1) {
- ret.type = (schar == '!' ? kExprLexNot : kExprLexAssignment);
- ret.data.ass.type = kExprAsgnPlain;
- break;
- }
- ret.type = kExprLexComparison;
- ret.data.cmp.inv = (schar == '!');
- if (pline.data[1] == '=') {
- ret.data.cmp.type = kExprCmpEqual;
- ret.len++;
- } else if (pline.data[1] == '~') {
- ret.data.cmp.type = kExprCmpMatches;
- ret.len++;
- } else if (schar == '!') {
- ret.type = kExprLexNot;
- } else {
- ret.type = kExprLexAssignment;
- ret.data.ass.type = kExprAsgnPlain;
- }
- GET_CCS(ret, pline);
+ break;
+
+ // Unary not, (un)equality and regex (not) match comparison operators.
+ case '!':
+ case '=':
+ if (pline.size == 1) {
+ ret.type = (schar == '!' ? kExprLexNot : kExprLexAssignment);
+ ret.data.ass.type = kExprAsgnPlain;
break;
}
-
- // Less/greater [or equal to] comparison operators.
- case '>':
- case '<': {
- ret.type = kExprLexComparison;
- const bool haseqsign = (pline.size > 1 && pline.data[1] == '=');
- if (haseqsign) {
- ret.len++;
- }
- GET_CCS(ret, pline);
- ret.data.cmp.inv = (schar == '<');
- ret.data.cmp.type = ((ret.data.cmp.inv ^ haseqsign)
+ ret.type = kExprLexComparison;
+ ret.data.cmp.inv = (schar == '!');
+ if (pline.data[1] == '=') {
+ ret.data.cmp.type = kExprCmpEqual;
+ ret.len++;
+ } else if (pline.data[1] == '~') {
+ ret.data.cmp.type = kExprCmpMatches;
+ ret.len++;
+ } else if (schar == '!') {
+ ret.type = kExprLexNot;
+ } else {
+ ret.type = kExprLexAssignment;
+ ret.data.ass.type = kExprAsgnPlain;
+ }
+ GET_CCS(ret, pline);
+ break;
+
+ // Less/greater [or equal to] comparison operators.
+ case '>':
+ case '<': {
+ ret.type = kExprLexComparison;
+ const bool haseqsign = (pline.size > 1 && pline.data[1] == '=');
+ if (haseqsign) {
+ ret.len++;
+ }
+ GET_CCS(ret, pline);
+ ret.data.cmp.inv = (schar == '<');
+ ret.data.cmp.type = ((ret.data.cmp.inv ^ haseqsign)
? kExprCmpGreaterOrEqual
: kExprCmpGreater);
- break;
- }
+ break;
+ }
- // Minus sign, arrow from lambdas or augmented assignment.
- case '-': {
- if (pline.size > 1 && pline.data[1] == '>') {
- ret.len++;
- ret.type = kExprLexArrow;
- } else if (pline.size > 1 && pline.data[1] == '=') {
- ret.len++;
- ret.type = kExprLexAssignment;
- ret.data.ass.type = kExprAsgnSubtract;
- } else {
- ret.type = kExprLexMinus;
- }
- break;
+ // Minus sign, arrow from lambdas or augmented assignment.
+ case '-': {
+ if (pline.size > 1 && pline.data[1] == '>') {
+ ret.len++;
+ ret.type = kExprLexArrow;
+ } else if (pline.size > 1 && pline.data[1] == '=') {
+ ret.len++;
+ ret.type = kExprLexAssignment;
+ ret.data.ass.type = kExprAsgnSubtract;
+ } else {
+ ret.type = kExprLexMinus;
}
+ break;
+ }
// Sign or augmented assignment.
#define CHAR_OR_ASSIGN(ch, ch_type, ass_type) \
- case ch: { \
- if (pline.size > 1 && pline.data[1] == '=') { \
- ret.len++; \
- ret.type = kExprLexAssignment; \
- ret.data.ass.type = ass_type; \
- } else { \
- ret.type = ch_type; \
- } \
- break; \
- }
+case ch: { \
+ if (pline.size > 1 && pline.data[1] == '=') { \
+ ret.len++; \
+ ret.type = kExprLexAssignment; \
+ ret.data.ass.type = ass_type; \
+ } else { \
+ ret.type = ch_type; \
+ } \
+ break; \
+}
CHAR_OR_ASSIGN('+', kExprLexPlus, kExprAsgnAdd)
CHAR_OR_ASSIGN('.', kExprLexDot, kExprAsgnConcat)
#undef CHAR_OR_ASSIGN
- // Expression end because Ex command ended.
- case NUL:
- case NL: {
- if (flags & kELFlagForbidEOC) {
- ret.type = kExprLexInvalid;
- ret.data.err.msg = _("E15: Unexpected EOC character: %.*s");
- ret.data.err.type = kExprLexSpacing;
- } else {
- ret.type = kExprLexEOC;
- }
- break;
- }
-
- case '|': {
- if (pline.size >= 2 && pline.data[ret.len] == '|') {
- // "||" is or.
- ret.len++;
- ret.type = kExprLexOr;
- } else if (flags & kELFlagForbidEOC) {
- // Note: `<C-r>=1 | 2<CR>` actually yields 1 in Vim without any
- // errors. This will be changed here.
- ret.type = kExprLexInvalid;
- ret.data.err.msg = _("E15: Unexpected EOC character: %.*s");
- ret.data.err.type = kExprLexOr;
- } else {
- ret.type = kExprLexEOC;
- }
- break;
+ // Expression end because Ex command ended.
+ case NUL:
+ case NL:
+ if (flags & kELFlagForbidEOC) {
+ ret.type = kExprLexInvalid;
+ ret.data.err.msg = _("E15: Unexpected EOC character: %.*s");
+ ret.data.err.type = kExprLexSpacing;
+ } else {
+ ret.type = kExprLexEOC;
}
-
- // Everything else is not valid.
- default: {
- ret.len = (size_t)utfc_ptr2len_len((const char_u *)pline.data,
- (int)pline.size);
+ break;
+
+ case '|':
+ if (pline.size >= 2 && pline.data[ret.len] == '|') {
+ // "||" is or.
+ ret.len++;
+ ret.type = kExprLexOr;
+ } else if (flags & kELFlagForbidEOC) {
+ // Note: `<C-r>=1 | 2<CR>` actually yields 1 in Vim without any
+ // errors. This will be changed here.
ret.type = kExprLexInvalid;
- ret.data.err.type = kExprLexPlainIdentifier;
- ret.data.err.msg = _("E15: Unidentified character: %.*s");
- break;
+ ret.data.err.msg = _("E15: Unexpected EOC character: %.*s");
+ ret.data.err.type = kExprLexOr;
+ } else {
+ ret.type = kExprLexEOC;
}
+ break;
+
+ // Everything else is not valid.
+ default:
+ ret.len = (size_t)utfc_ptr2len_len((const char_u *)pline.data,
+ (int)pline.size);
+ ret.type = kExprLexInvalid;
+ ret.data.err.type = kExprLexPlainIdentifier;
+ ret.data.err.msg = _("E15: Unidentified character: %.*s");
+ break;
}
#undef GET_CCS
viml_pexpr_next_token_adv_return:
@@ -737,8 +793,7 @@ static const char *const eltkn_opt_scope_tab[] = {
///
/// @return Token represented in a string form, in a static buffer (overwritten
/// on each call).
-const char *viml_pexpr_repr_token(const ParserState *const pstate,
- const LexExprToken token,
+const char *viml_pexpr_repr_token(const ParserState *const pstate, const LexExprToken token,
size_t *const ret_size)
FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -756,10 +811,10 @@ const char *viml_pexpr_repr_token(const ParserState *const pstate,
eltkn_type_tab[token.type]);
switch (token.type) {
#define TKNARGS(tkn_type, ...) \
- case tkn_type: { \
- ADDSTR(__VA_ARGS__); \
- break; \
- }
+case tkn_type: { \
+ ADDSTR(__VA_ARGS__); \
+ break; \
+}
TKNARGS(kExprLexComparison, "(type=%s,ccs=%s,inv=%i)",
eltkn_cmp_type_tab[token.data.cmp.type],
ccs_tab[token.data.cmp.ccs],
@@ -769,7 +824,7 @@ const char *viml_pexpr_repr_token(const ParserState *const pstate,
TKNARGS(kExprLexAssignment, "(type=%s)",
expr_asgn_type_tab[token.data.ass.type])
TKNARGS(kExprLexRegister, "(name=%s)", intchar2str(token.data.reg.name))
- case kExprLexDoubleQuotedString:
+ case kExprLexDoubleQuotedString:
TKNARGS(kExprLexSingleQuotedString, "(closed=%i)",
(int)token.data.str.closed)
TKNARGS(kExprLexOption, "(scope=%s,name=%.*s)",
@@ -785,19 +840,17 @@ const char *viml_pexpr_repr_token(const ParserState *const pstate,
? (double)token.data.num.val.floating
: (double)token.data.num.val.integer))
TKNARGS(kExprLexInvalid, "(msg=%s)", token.data.err.msg)
- default: {
- // No additional arguments.
- break;
- }
+ default:
+ // No additional arguments.
+ break;
#undef TKNARGS
}
if (pstate == NULL) {
ADDSTR("::%zu", token.len);
} else {
*p++ = ':';
- memmove(
- p, &pstate->reader.lines.items[token.start.line].data[token.start.col],
- token.len);
+ memmove(p, &pstate->reader.lines.items[token.start.line].data[token.start.col],
+ token.len);
p += token.len;
*p = NUL;
}
@@ -886,9 +939,8 @@ static const char *intchar2str(const int ch)
#include <stdio.h>
REAL_FATTR_UNUSED
-static inline void viml_pexpr_debug_print_ast_node(
- const ExprASTNode *const *const eastnode_p,
- const char *const prefix)
+static inline void viml_pexpr_debug_print_ast_node(const ExprASTNode *const *const eastnode_p,
+ const char *const prefix)
{
if (*eastnode_p == NULL) {
fprintf(stderr, "%s %p : NULL\n", prefix, (void *)eastnode_p);
@@ -901,35 +953,33 @@ static inline void viml_pexpr_debug_print_ast_node(
}
REAL_FATTR_UNUSED
-static inline void viml_pexpr_debug_print_ast_stack(
- const ExprASTStack *const ast_stack,
- const char *const msg)
+static inline void viml_pexpr_debug_print_ast_stack(const ExprASTStack *const ast_stack,
+ const char *const msg)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
{
fprintf(stderr, "\n%sstack: %zu:\n", msg, kv_size(*ast_stack));
for (size_t i = 0; i < kv_size(*ast_stack); i++) {
- viml_pexpr_debug_print_ast_node(
- (const ExprASTNode *const *)kv_A(*ast_stack, i),
- "-");
+ viml_pexpr_debug_print_ast_node((const ExprASTNode *const *)kv_A(*ast_stack, i),
+ "-");
}
}
REAL_FATTR_UNUSED
-static inline void viml_pexpr_debug_print_token(
- const ParserState *const pstate, const LexExprToken token)
+static inline void viml_pexpr_debug_print_token(const ParserState *const pstate,
+ const LexExprToken token)
FUNC_ATTR_ALWAYS_INLINE
{
fprintf(stderr, "\ntkn: %s\n", viml_pexpr_repr_token(pstate, token, NULL));
}
#define PSTACK(msg) \
- viml_pexpr_debug_print_ast_stack(&ast_stack, #msg)
+ viml_pexpr_debug_print_ast_stack(&ast_stack, #msg)
#define PSTACK_P(msg) \
- viml_pexpr_debug_print_ast_stack(ast_stack, #msg)
+ viml_pexpr_debug_print_ast_stack(ast_stack, #msg)
#define PNODE_P(eastnode_p, msg) \
- viml_pexpr_debug_print_ast_node((const E