diff options
-rw-r--r-- | src/nvim/viml/parser/expressions.c | 17 | ||||
-rw-r--r-- | test/unit/viml/expressions/parser_spec.lua | 113 |
2 files changed, 128 insertions, 2 deletions
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index 4801d66988..35f4385f33 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -1042,6 +1042,7 @@ void viml_pexpr_free_ast(ExprAST ast) // // NVimRegister -> SpecialChar // NVimNumber -> Number +// NVimNumberPrefix -> SpecialChar // NVimFloat -> NVimNumber // // NVimNestingParenthesis -> NVimParenthesis @@ -1842,6 +1843,14 @@ static const int want_node_to_lexer_flags[] = { [kENodeArgumentSeparator] = kELFlagForbidScope, }; +/// Number of characters to highlight as NumberPrefix depending on the base +static const uint8_t base_to_prefix_length[] = { + [2] = 2, + [8] = 1, + [10] = 0, + [16] = 2, +}; + /// Parse one VimL expression /// /// @param pstate Parser state. @@ -2632,7 +2641,13 @@ viml_pexpr_parse_figure_brace_closing_error: } else { NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeInteger); cur_node->data.num.value = cur_token.data.num.val.integer; - HL_CUR_TOKEN(Number); + const uint8_t prefix_length = base_to_prefix_length[ + cur_token.data.num.base]; + viml_parser_highlight(pstate, cur_token.start, prefix_length, + HL(NumberPrefix)); + viml_parser_highlight( + pstate, shifted_pos(cur_token.start, prefix_length), + cur_token.len - prefix_length, HL(Number)); } want_node = kENodeOperator; *top_node_p = cur_node; diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua index 36af875bd2..54fd54aea8 100644 --- a/test/unit/viml/expressions/parser_spec.lua +++ b/test/unit/viml/expressions/parser_spec.lua @@ -6858,6 +6858,116 @@ describe('Expressions parser', function() hl('Number', '2'), }) end) + itp('highlights numbers with prefix', function() + check_parsing('0xABCDEF', 0, { + -- 01234567 + ast = { + 'Integer(val=11259375):0:0:0xABCDEF', + }, + }, { + hl('NumberPrefix', '0x'), + hl('Number', 'ABCDEF'), + }) + + check_parsing('0Xabcdef', 0, { + -- 01234567 + ast = { + 'Integer(val=11259375):0:0:0Xabcdef', + }, + }, { + hl('NumberPrefix', '0X'), + hl('Number', 'abcdef'), + }) + + check_parsing('0XABCDEF', 0, { + -- 01234567 + ast = { + 'Integer(val=11259375):0:0:0XABCDEF', + }, + }, { + hl('NumberPrefix', '0X'), + hl('Number', 'ABCDEF'), + }) + + check_parsing('0xabcdef', 0, { + -- 01234567 + ast = { + 'Integer(val=11259375):0:0:0xabcdef', + }, + }, { + hl('NumberPrefix', '0x'), + hl('Number', 'abcdef'), + }) + + check_parsing('0b001', 0, { + -- 01234 + ast = { + 'Integer(val=1):0:0:0b001', + }, + }, { + hl('NumberPrefix', '0b'), + hl('Number', '001'), + }) + + check_parsing('0B001', 0, { + -- 01234 + ast = { + 'Integer(val=1):0:0:0B001', + }, + }, { + hl('NumberPrefix', '0B'), + hl('Number', '001'), + }) + + check_parsing('0B00', 0, { + -- 0123 + ast = { + 'Integer(val=0):0:0:0B00', + }, + }, { + hl('NumberPrefix', '0B'), + hl('Number', '00'), + }) + + check_parsing('00', 0, { + -- 01 + ast = { + 'Integer(val=0):0:0:00', + }, + }, { + hl('NumberPrefix', '0'), + hl('Number', '0'), + }) + + check_parsing('001', 0, { + -- 012 + ast = { + 'Integer(val=1):0:0:001', + }, + }, { + hl('NumberPrefix', '0'), + hl('Number', '01'), + }) + + check_parsing('01', 0, { + -- 01 + ast = { + 'Integer(val=1):0:0:01', + }, + }, { + hl('NumberPrefix', '0'), + hl('Number', '1'), + }) + + check_parsing('1', 0, { + -- 0 + ast = { + 'Integer(val=1):0:0:1', + }, + }, { + hl('Number', '1'), + }) + end) itp('works (KLEE tests)', function() check_parsing('\0002&A:\000', 0, { ast = nil, @@ -6879,7 +6989,8 @@ describe('Expressions parser', function() 'Integer(val=0):0:0:00', }, }, { - hl('Number', '00'), + hl('NumberPrefix', '0'), + hl('Number', '0'), }) end) end) |