From b9d5aea073521f3278bea257be306b7ac2b8d83c Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 3 Nov 2017 11:38:59 +0300 Subject: api/vim: Create part of nvim_parse_expression function --- test/functional/api/vim_spec.lua | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index b849304d45..6b44698638 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -710,4 +710,9 @@ describe('api', function() ok(err:match(': Wrong type for argument 1, expecting String') ~= nil) end) + describe('nvim_parse_expression', function() + -- FIXME + -- FIXME Test error + end) + end) -- cgit From 7bc6de75263f58c6c4f999bc86a6454ae9f28b80 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 5 Nov 2017 02:41:44 +0300 Subject: api/vim,functests: Add tests for nvim_parse_expression, fix found bugs --- test/functional/api/vim_spec.lua | 6868 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 6868 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 6b44698638..bb7785657d 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,5 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') +local global_helpers = require('test.helpers') + local NIL = helpers.NIL local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed @@ -10,6 +12,9 @@ local request = helpers.request local meth_pcall = helpers.meth_pcall local command = helpers.command +local intchar2lua = global_helpers.intchar2lua +local format_string = global_helpers.format_string + describe('api', function() before_each(clear) @@ -711,8 +716,6871 @@ describe('api', function() end) describe('nvim_parse_expression', function() + local function simplify_east_api_node(line, east_api_node) + if east_api_node.children then + for k, v in pairs(east_api_node.children) do + east_api_node.children[k] = simplify_east_api_node(line, v) + end + end + local typ = east_api_node.type + if typ == 'Register' then + typ = typ .. ('(name=%s)'):format( + tostring(intchar2lua(east_api_node.name))) + east_api_node.name = nil + elseif typ == 'PlainIdentifier' then + typ = typ .. ('(scope=%s,ident=%s)'):format( + tostring(intchar2lua(east_api_node.scope)), east_api_node.ident) + east_api_node.scope = nil + east_api_node.ident = nil + elseif typ == 'PlainKey' then + typ = typ .. ('(key=%s)'):format(east_api_node.ident) + east_api_node.ident = nil + elseif typ == 'Comparison' then + typ = typ .. ('(type=%s,inv=%u,ccs=%s)'):format( + east_api_node.cmp_type, east_api_node.invert and 1 or 0, + east_api_node.ccs_strategy) + east_api_node.ccs_strategy = nil + east_api_node.cmp_type = nil + east_api_node.invert = nil + elseif typ == 'Integer' then + typ = typ .. ('(val=%u)'):format(east_api_node.ivalue) + east_api_node.ivalue = nil + elseif typ == 'Float' then + typ = typ .. ('(val=%e)'):format(east_api_node.fvalue) + east_api_node.fvalue = nil + elseif typ == 'SingleQuotedString' or typ == 'DoubleQuotedString' then + typ = format_string('%s(val=%q)', typ, east_api_node.svalue) + east_api_node.svalue = nil + elseif typ == 'Option' then + typ = ('%s(scope=%s,ident=%s)'):format( + typ, + tostring(intchar2lua(east_api_node.scope)), + east_api_node.ident) + east_api_node.ident = nil + east_api_node.scope = nil + elseif typ == 'Environment' then + typ = ('%s(ident=%s)'):format(typ, east_api_node.ident) + east_api_node.ident = nil + end + typ = ('%s:%u:%u:%s'):format( + typ, east_api_node.start[1], east_api_node.start[2], + line:sub(east_api_node.start[2] + 1, + east_api_node.start[2] + 1 + east_api_node.len - 1)) + assert(east_api_node.start[2] + east_api_node.len - 1 <= #line) + for k, _ in pairs(east_api_node.start) do + assert(({true, true})[k]) + end + east_api_node.start = nil + east_api_node.type = nil + east_api_node.len = nil + local can_simplify = true + for _, _ in pairs(east_api_node) do + if can_simplify then can_simplify = false end + end + if can_simplify then + return typ + else + east_api_node[1] = typ + return east_api_node + end + end + local function simplify_east_api(line, east_api) + if east_api.error then + east_api.err = east_api.error + east_api.error = nil + east_api.err.msg = east_api.err.message + east_api.err.message = nil + end + if east_api.ast then + east_api.ast = {simplify_east_api_node(line, east_api.ast)} + end + return east_api + end + local function simplify_east_hl(line, east_hl) + for i, v in ipairs(east_hl) do + east_hl[i] = ('%s:%u:%u:%s'):format( + v[4], + v[1], + v[2], + line:sub(v[2] + 1, v[3])) + end + return east_hl + end + local function check_parsing(str, flags, exp_ast, exp_highlighting_fs) + if flags == 0 then + flags = "" + end + + local err, msg = pcall(function() + local east_api = meths.parse_expression(str, flags, true) + local east_hl = east_api.highlight + east_api.highlight = nil + local ast = simplify_east_api(str, east_api) + local hls = simplify_east_hl(str, east_hl) + eq(exp_ast, ast) + if exp_highlighting_fs then + local exp_highlighting = {} + local next_col = 0 + for i, h in ipairs(exp_highlighting_fs) do + exp_highlighting[i], next_col = h(next_col) + end + eq(exp_highlighting, hls) + end + end) + if not err then + msg = format_string('Error while processing test (%r, %s):\n%s', + str, flags, msg) + error(msg) + end + end + local function hl(group, str, shift) + return function(next_col) + local col = next_col + (shift or 0) + return (('%s:%u:%u:%s'):format( + 'NVim' .. group, + 0, + col, + str)), (col + #str) + end + end + it('works with + and @a', function() + check_parsing('@a', 0, { + ast = { + 'Register(name=a):0:0:@a', + }, + }, { + hl('Register', '@a'), + }) + check_parsing('+@a', 0, { + ast = { + { + 'UnaryPlus:0:0:+', + children = { + 'Register(name=a):0:1:@a', + }, + }, + }, + }, { + hl('UnaryPlus', '+'), + hl('Register', '@a'), + }) + check_parsing('@a+@b', 0, { + ast = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + 'Register(name=b):0:3:@b', + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('Register', '@b'), + }) + check_parsing('@a+@b+@c', 0, { + ast = { + { + 'BinaryPlus:0:5:+', + children = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + 'Register(name=b):0:3:@b', + }, + }, + 'Register(name=c):0:6:@c', + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('Register', '@b'), + hl('BinaryPlus', '+'), + hl('Register', '@c'), + }) + check_parsing('+@a+@b', 0, { + ast = { + { + 'BinaryPlus:0:3:+', + children = { + { + 'UnaryPlus:0:0:+', + children = { + 'Register(name=a):0:1:@a', + }, + }, + 'Register(name=b):0:4:@b', + }, + }, + }, + }, { + hl('UnaryPlus', '+'), + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('Register', '@b'), + }) + check_parsing('+@a++@b', 0, { + ast = { + { + 'BinaryPlus:0:3:+', + children = { + { + 'UnaryPlus:0:0:+', + children = { + 'Register(name=a):0:1:@a', + }, + }, + { + 'UnaryPlus:0:4:+', + children = { + 'Register(name=b):0:5:@b', + }, + }, + }, + }, + }, + }, { + hl('UnaryPlus', '+'), + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('UnaryPlus', '+'), + hl('Register', '@b'), + }) + check_parsing('@a@b', 0, { + ast = { + { + 'OpMissing:0:2:', + children = { + 'Register(name=a):0:0:@a', + 'Register(name=b):0:2:@b', + }, + }, + }, + err = { + arg = '@b', + msg = 'E15: Missing operator: %.*s', + }, + }, { + hl('Register', '@a'), + hl('InvalidRegister', '@b'), + }) + check_parsing(' @a \t @b', 0, { + ast = { + { + 'OpMissing:0:3:', + children = { + 'Register(name=a):0:0: @a', + 'Register(name=b):0:3: \t @b', + }, + }, + }, + err = { + arg = '@b', + msg = 'E15: Missing operator: %.*s', + }, + }, { + hl('Register', '@a', 1), + hl('InvalidSpacing', ' \t '), + hl('Register', '@b'), + }) + check_parsing('+', 0, { + ast = { + 'UnaryPlus:0:0:+', + }, + err = { + arg = '', + msg = 'E15: Expected value, got EOC: %.*s', + }, + }, { + hl('UnaryPlus', '+'), + }) + check_parsing(' +', 0, { + ast = { + 'UnaryPlus:0:0: +', + }, + err = { + arg = '', + msg = 'E15: Expected value, got EOC: %.*s', + }, + }, { + hl('UnaryPlus', '+', 1), + }) + check_parsing('@a+ ', 0, { + ast = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + }, + }, + }, + err = { + arg = '', + msg = 'E15: Expected value, got EOC: %.*s', + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + }) + end) + it('works with @a, + and parenthesis', function() + check_parsing('(@a)', 0, { + ast = { + { + 'Nested:0:0:(', + children = { + 'Register(name=a):0:1:@a', + }, + }, + }, + }, { + hl('NestingParenthesis', '('), + hl('Register', '@a'), + hl('NestingParenthesis', ')'), + }) + check_parsing('()', 0, { + ast = { + { + 'Nested:0:0:(', + children = { + 'Missing:0:1:', + }, + }, + }, + err = { + arg = ')', + msg = 'E15: Expected value, got parenthesis: %.*s', + }, + }, { + hl('NestingParenthesis', '('), + hl('InvalidNestingParenthesis', ')'), + }) + check_parsing(')', 0, { + ast = { + { + 'Nested:0:0:', + children = { + 'Missing:0:0:', + }, + }, + }, + err = { + arg = ')', + msg = 'E15: Expected value, got parenthesis: %.*s', + }, + }, { + hl('InvalidNestingParenthesis', ')'), + }) + check_parsing('+)', 0, { + ast = { + { + 'Nested:0:1:', + children = { + { + 'UnaryPlus:0:0:+', + children = { + 'Missing:0:1:', + }, + }, + }, + }, + }, + err = { + arg = ')', + msg = 'E15: Expected value, got parenthesis: %.*s', + }, + }, { + hl('UnaryPlus', '+'), + hl('InvalidNestingParenthesis', ')'), + }) + check_parsing('+@a(@b)', 0, { + ast = { + { + 'UnaryPlus:0:0:+', + children = { + { + 'Call:0:3:(', + children = { + 'Register(name=a):0:1:@a', + 'Register(name=b):0:4:@b', + }, + }, + }, + }, + }, + }, { + hl('UnaryPlus', '+'), + hl('Register', '@a'), + hl('CallingParenthesis', '('), + hl('Register', '@b'), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a+@b(@c)', 0, { + ast = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + { + 'Call:0:5:(', + children = { + 'Register(name=b):0:3:@b', + 'Register(name=c):0:6:@c', + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('Register', '@b'), + hl('CallingParenthesis', '('), + hl('Register', '@c'), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a()', 0, { + ast = { + { + 'Call:0:2:(', + children = { + 'Register(name=a):0:0:@a', + }, + }, + }, + }, { + hl('Register', '@a'), + hl('CallingParenthesis', '('), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a ()', 0, { + ast = { + { + 'OpMissing:0:2:', + children = { + 'Register(name=a):0:0:@a', + { + 'Nested:0:2: (', + children = { + 'Missing:0:4:', + }, + }, + }, + }, + }, + err = { + arg = '()', + msg = 'E15: Missing operator: %.*s', + }, + }, { + hl('Register', '@a'), + hl('InvalidSpacing', ' '), + hl('NestingParenthesis', '('), + hl('InvalidNestingParenthesis', ')'), + }) + check_parsing( + '@a + (@b)', 0, { + ast = { + { + 'BinaryPlus:0:2: +', + children = { + 'Register(name=a):0:0:@a', + { + 'Nested:0:4: (', + children = { + 'Register(name=b):0:6:@b', + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+', 1), + hl('NestingParenthesis', '(', 1), + hl('Register', '@b'), + hl('NestingParenthesis', ')'), + }) + check_parsing( + '@a + (+@b)', 0, { + ast = { + { + 'BinaryPlus:0:2: +', + children = { + 'Register(name=a):0:0:@a', + { + 'Nested:0:4: (', + children = { + { + 'UnaryPlus:0:6:+', + children = { + 'Register(name=b):0:7:@b', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+', 1), + hl('NestingParenthesis', '(', 1), + hl('UnaryPlus', '+'), + hl('Register', '@b'), + hl('NestingParenthesis', ')'), + }) + check_parsing( + '@a + (@b + @c)', 0, { + ast = { + { + 'BinaryPlus:0:2: +', + children = { + 'Register(name=a):0:0:@a', + { + 'Nested:0:4: (', + children = { + { + 'BinaryPlus:0:8: +', + children = { + 'Register(name=b):0:6:@b', + 'Register(name=c):0:10: @c', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+', 1), + hl('NestingParenthesis', '(', 1), + hl('Register', '@b'), + hl('BinaryPlus', '+', 1), + hl('Register', '@c', 1), + hl('NestingParenthesis', ')'), + }) + check_parsing('(@a)+@b', 0, { + ast = { + { + 'BinaryPlus:0:4:+', + children = { + { + 'Nested:0:0:(', + children = { + 'Register(name=a):0:1:@a', + }, + }, + 'Register(name=b):0:5:@b', + }, + }, + }, + }, { + hl('NestingParenthesis', '('), + hl('Register', '@a'), + hl('NestingParenthesis', ')'), + hl('BinaryPlus', '+'), + hl('Register', '@b'), + }) + check_parsing('@a+(@b)(@c)', 0, { + -- 01234567890 + ast = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + { + 'Call:0:7:(', + children = { + { + 'Nested:0:3:(', + children = { 'Register(name=b):0:4:@b' }, + }, + 'Register(name=c):0:8:@c', + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('NestingParenthesis', '('), + hl('Register', '@b'), + hl('NestingParenthesis', ')'), + hl('CallingParenthesis', '('), + hl('Register', '@c'), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a+((@b))(@c)', 0, { + -- 01234567890123456890123456789 + -- 0 1 2 + ast = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + { + 'Call:0:9:(', + children = { + { + 'Nested:0:3:(', + children = { + { + 'Nested:0:4:(', + children = { 'Register(name=b):0:5:@b' } + }, + }, + }, + 'Register(name=c):0:10:@c', + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('NestingParenthesis', '('), + hl('NestingParenthesis', '('), + hl('Register', '@b'), + hl('NestingParenthesis', ')'), + hl('NestingParenthesis', ')'), + hl('CallingParenthesis', '('), + hl('Register', '@c'), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a+((@b))+@c', 0, { + -- 01234567890123456890123456789 + -- 0 1 2 + ast = { + { + 'BinaryPlus:0:9:+', + children = { + { + 'BinaryPlus:0:2:+', + children = { + 'Register(name=a):0:0:@a', + { + 'Nested:0:3:(', + children = { + { + 'Nested:0:4:(', + children = { 'Register(name=b):0:5:@b' } + }, + }, + }, + }, + }, + 'Register(name=c):0:10:@c', + }, + }, + }, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('NestingParenthesis', '('), + hl('NestingParenthesis', '('), + hl('Register', '@b'), + hl('NestingParenthesis', ')'), + hl('NestingParenthesis', ')'), + hl('BinaryPlus', '+'), + hl('Register', '@c'), + }) + check_parsing( + '@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', 0, {--[[ + | | | | | | | | || | | || | | ||| || || || || + 000000000011111111112222222222333333333344444444445555555 + 012345678901234567890123456789012345678901234567890123456 + ]] + ast = {{ + 'BinaryPlus:0:31: +', + children = { + { + 'BinaryPlus:0:23: +', + children = { + { + 'BinaryPlus:0:14: +', + children = { + { + 'BinaryPlus:0:2: +', + children = { + 'Register(name=a):0:0:@a', + { + 'Nested:0:4: (', + children = { + { + 'BinaryPlus:0:8: +', + children = { + 'Register(name=b):0:6:@b', + 'Register(name=c):0:10: @c', + }, + }, + }, + }, + }, + }, + { + 'Call:0:19:(', + children = { + 'Register(name=d):0:16: @d', + 'Register(name=e):0:20:@e', + }, + }, + }, + }, + { + 'Nested:0:25: (', + children = { + { + 'UnaryPlus:0:27:+', + children = { + 'Register(name=f):0:28:@f', + }, + }, + }, + }, + }, + }, + { + 'Call:0:53:(', + children = { + { + 'Nested:0:33: (', + children = { + { + 'Call:0:48:(', + children = { + { + 'Call:0:44:(', + children = { + { + 'Nested:0:35:(', + children = { + { + 'UnaryPlus:0:36:+', + children = { + { + 'Call:0:39:(', + children = { + 'Register(name=g):0:37:@g', + 'Register(name=h):0:40:@h', + }, + }, + }, + }, + }, + }, + 'Register(name=j):0:45:@j', + }, + }, + 'Register(name=k):0:49:@k', + }, + }, + }, + }, + 'Register(name=l):0:54:@l', + }, + }, + }, + }}, + }, { + hl('Register', '@a'), + hl('BinaryPlus', '+', 1), + hl('NestingParenthesis', '(', 1), + hl('Register', '@b'), + hl('BinaryPlus', '+', 1), + hl('Register', '@c', 1), + hl('NestingParenthesis', ')'), + hl('BinaryPlus', '+', 1), + hl('Register', '@d', 1), + hl('CallingParenthesis', '('), + hl('Register', '@e'), + hl('CallingParenthesis', ')'), + hl('BinaryPlus', '+', 1), + hl('NestingParenthesis', '(', 1), + hl('UnaryPlus', '+'), + hl('Register', '@f'), + hl('NestingParenthesis', ')'), + hl('BinaryPlus', '+', 1), + hl('NestingParenthesis', '(', 1), + hl('NestingParenthesis', '('), + hl('UnaryPlus', '+'), + hl('Register', '@g'), + hl('CallingParenthesis', '('), + hl('Register', '@h'), + hl('CallingParenthesis', ')'), + hl('NestingParenthesis', ')'), + hl('CallingParenthesis', '('), + hl('Register', '@j'), + hl('CallingParenthesis', ')'), + hl('CallingParenthesis', '('), + hl('Register', '@k'), + hl('CallingParenthesis', ')'), + hl('NestingParenthesis', ')'), + hl('CallingParenthesis', '('), + hl('Register', '@l'), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a)', 0, { + -- 012 + ast = { + { + 'Nested:0:2:', + children = { + 'Register(name=a):0:0:@a', + }, + }, + }, + err = { + arg = ')', + msg = 'E15: Unexpected closing parenthesis: %.*s', + }, + }, { + hl('Register', '@a'), + hl('InvalidNestingParenthesis', ')'), + }) + check_parsing('(@a', 0, { + -- 012 + ast = { + { + 'Nested:0:0:(', + children = { + 'Register(name=a):0:1:@a', + }, + }, + }, + err = { + arg = '(@a', + msg = 'E110: Missing closing parenthesis for nested expression: %.*s', + }, + }, { + hl('NestingParenthesis', '('), + hl('Register', '@a'), + }) + check_parsing('@a(@b', 0, { + -- 01234 + ast = { + { + 'Call:0:2:(', + children = { + 'Register(name=a):0:0:@a', + 'Register(name=b):0:3:@b', + }, + }, + }, + err = { + arg = '(@b', + msg = 'E116: Missing closing parenthesis for function call: %.*s', + }, + }, { + hl('Register', '@a'), + hl('CallingParenthesis', '('), + hl('Register', '@b'), + }) + check_parsing('@a(@b, @c, @d, @e)', 0, { + -- 012345678901234567 + -- 0 1 + ast = { + { + 'Call:0:2:(', + children = { + 'Register(name=a):0:0:@a', + { + 'Comma:0:5:,', + children = { + 'Register(name=b):0:3:@b', + { + 'Comma:0:9:,', + children = { + 'Register(name=c):0:6: @c', + { + 'Comma:0:13:,', + children = { + 'Register(name=d):0:10: @d', + 'Register(name=e):0:14: @e', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('CallingParenthesis', '('), + hl('Register', '@b'), + hl('Comma', ','), + hl('Register', '@c', 1), + hl('Comma', ','), + hl('Register', '@d', 1), + hl('Comma', ','), + hl('Register', '@e', 1), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a(@b(@c))', 0, { + -- 01234567890123456789012345678901234567 + -- 0 1 2 3 + ast = { + { + 'Call:0:2:(', + children = { + 'Register(name=a):0:0:@a', + { + 'Call:0:5:(', + children = { + 'Register(name=b):0:3:@b', + 'Register(name=c):0:6:@c', + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('CallingParenthesis', '('), + hl('Register', '@b'), + hl('CallingParenthesis', '('), + hl('Register', '@c'), + hl('CallingParenthesis', ')'), + hl('CallingParenthesis', ')'), + }) + check_parsing('@a(@b(@c(@d(@e), @f(@g(@h), @i(@j)))))', 0, { + -- 01234567890123456789012345678901234567 + -- 0 1 2 3 + ast = { + { + 'Call:0:2:(', + children = { + 'Register(name=a):0:0:@a', + { + 'Call:0:5:(', + children = { + 'Register(name=b):0:3:@b', + { + 'Call:0:8:(', + children = { + 'Register(name=c):0:6:@c', + { + 'Comma:0:15:,', + children = { + { + 'Call:0:11:(', + children = { + 'Register(name=d):0:9:@d', + 'Register(name=e):0:12:@e', + }, + }, + { + 'Call:0:19:(', + children = { + 'Register(name=f):0:16: @f', + { + 'Comma:0:26:,', + children = { + { + 'Call:0:22:(', + children = { + 'Register(name=g):0:20:@g', + 'Register(name=h):0:23:@h', + }, + }, + { + 'Call:0:30:(', + children = { + 'Register(name=i):0:27: @i', + 'Register(name=j):0:31:@j', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Register', '@a'), + hl('CallingParenthesis', '('), + hl('Register', '@b'), + hl('CallingParenthesis', '('), + hl('Register', '@c'), + hl('CallingParenthesis', '('), + hl('Register', '@d'), + hl('CallingParenthesis', '('), + hl('Register', '@e'), + hl('CallingParenthesis', ')'), + hl('Comma', ','), + hl('Register', '@f', 1), + hl('CallingParenthesis', '('), + hl('Register', '@g'), + hl('CallingParenthesis', '('), + hl('Register', '@h'), + hl('CallingParenthesis', ')'), + hl('Comma', ','), + hl('Register', '@i', 1), + hl('CallingParenthesis', '('), + hl('Register', '@j'), + hl('CallingParenthesis', ')'), + hl('CallingParenthesis', ')'), + hl('CallingParenthesis', ')'), + hl('CallingParenthesis', ')'), + hl('CallingParenthesis', ')'), + }) + end) + it('works with variable names, including curly braces ones', function() + check_parsing('var', 0, { + ast = { + 'PlainIdentifier(scope=0,ident=var):0:0:var', + }, + }, { + hl('IdentifierName', 'var'), + }) + check_parsing('g:var', 0, { + ast = { + 'PlainIdentifier(scope=g,ident=var):0:0:g:var', + }, + }, { + hl('IdentifierScope', 'g'), + hl('IdentifierScopeDelimiter', ':'), + hl('IdentifierName', 'var'), + }) + check_parsing('g:', 0, { + ast = { + 'PlainIdentifier(scope=g,ident=):0:0:g:', + }, + }, { + hl('IdentifierScope', 'g'), + hl('IdentifierScopeDelimiter', ':'), + }) + check_parsing('{a}', 0, { + -- 012 + ast = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + }, + }, + }, + }, { + hl('Curly', '{'), + hl('IdentifierName', 'a'), + hl('Curly', '}'), + }) + check_parsing('{a:b}', 0, { + -- 012 + ast = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + 'PlainIdentifier(scope=a,ident=b):0:1:a:b', + }, + }, + }, + }, { + hl('Curly', '{'), + hl('IdentifierScope', 'a'), + hl('IdentifierScopeDelimiter', ':'), + hl('IdentifierName', 'b'), + hl('Curly', '}'), + }) + check_parsing('{a:@b}', 0, { + -- 012345 + ast = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + { + 'OpMissing:0:3:', + children={ + 'PlainIdentifier(scope=a,ident=):0:1:a:', + 'Register(name=b):0:3:@b', + }, + }, + }, + }, + }, + err = { + arg = '@b}', + msg = 'E15: Missing operator: %.*s', + }, + }, { + hl('Curly', '{'), + hl('IdentifierScope', 'a'), + hl('IdentifierScopeDelimiter', ':'), + hl('InvalidRegister', '@b'), + hl('Curly', '}'), + }) + check_parsing('{@a}', 0, { + ast = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + 'Register(name=a):0:1:@a', + }, + }, + }, + }, { + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + }) + check_parsing('{@a}{@b}', 0, { + -- 01234567 + ast = { + { + 'ComplexIdentifier:0:4:', + children = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + 'Register(name=a):0:1:@a', + }, + }, + { + 'CurlyBracesIdentifier:0:4:{', + children = { + 'Register(name=b):0:5:@b', + }, + }, + }, + }, + }, + }, { + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + hl('Curly', '{'), + hl('Register', '@b'), + hl('Curly', '}'), + }) + check_parsing('g:{@a}', 0, { + -- 01234567 + ast = { + { + 'ComplexIdentifier:0:2:', + children = { + 'PlainIdentifier(scope=g,ident=):0:0:g:', + { + 'CurlyBracesIdentifier:0:2:{', + children = { + 'Register(name=a):0:3:@a', + }, + }, + }, + }, + }, + }, { + hl('IdentifierScope', 'g'), + hl('IdentifierScopeDelimiter', ':'), + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + }) + check_parsing('{@a}_test', 0, { + -- 012345678 + ast = { + { + 'ComplexIdentifier:0:4:', + children = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + 'Register(name=a):0:1:@a', + }, + }, + 'PlainIdentifier(scope=0,ident=_test):0:4:_test', + }, + }, + }, + }, { + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + hl('IdentifierName', '_test'), + }) + check_parsing('g:{@a}_test', 0, { + -- 01234567890 + ast = { + { + 'ComplexIdentifier:0:2:', + children = { + 'PlainIdentifier(scope=g,ident=):0:0:g:', + { + 'ComplexIdentifier:0:6:', + children = { + { + 'CurlyBracesIdentifier:0:2:{', + children = { + 'Register(name=a):0:3:@a', + }, + }, + 'PlainIdentifier(scope=0,ident=_test):0:6:_test', + }, + }, + }, + }, + }, + }, { + hl('IdentifierScope', 'g'), + hl('IdentifierScopeDelimiter', ':'), + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + hl('IdentifierName', '_test'), + }) + check_parsing('g:{@a}_test()', 0, { + -- 0123456789012 + ast = { + { + 'Call:0:11:(', + children = { + { + 'ComplexIdentifier:0:2:', + children = { + 'PlainIdentifier(scope=g,ident=):0:0:g:', + { + 'ComplexIdentifier:0:6:', + children = { + { + 'CurlyBracesIdentifier:0:2:{', + children = { + 'Register(name=a):0:3:@a', + }, + }, + 'PlainIdentifier(scope=0,ident=_test):0:6:_test', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('IdentifierScope', 'g'), + hl('IdentifierScopeDelimiter', ':'), + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + hl('IdentifierName', '_test'), + hl('CallingParenthesis', '('), + hl('CallingParenthesis', ')'), + }) + check_parsing('{@a} ()', 0, { + -- 0123456789012 + ast = { + { + 'Call:0:4: (', + children = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + 'Register(name=a):0:1:@a', + }, + }, + }, + }, + }, + }, { + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + hl('CallingParenthesis', '(', 1), + hl('CallingParenthesis', ')'), + }) + check_parsing('g:{@a} ()', 0, { + -- 0123456789012 + ast = { + { + 'Call:0:6: (', + children = { + { + 'ComplexIdentifier:0:2:', + children = { + 'PlainIdentifier(scope=g,ident=):0:0:g:', + { + 'CurlyBracesIdentifier:0:2:{', + children = { + 'Register(name=a):0:3:@a', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('IdentifierScope', 'g'), + hl('IdentifierScopeDelimiter', ':'), + hl('Curly', '{'), + hl('Register', '@a'), + hl('Curly', '}'), + hl('CallingParenthesis', '(', 1), + hl('CallingParenthesis', ')'), + }) + check_parsing('{@a', 0, { + -- 012 + ast = { + { + 'UnknownFigure:0:0:{', + children = { + 'Register(name=a):0:1:@a', + }, + }, + }, + err = { + arg = '{@a', + msg = 'E15: Missing closing figure brace: %.*s', + }, + }, { + hl('FigureBrace', '{'), + hl('Register', '@a'), + }) + end) + it('works with lambdas and dictionaries', function() + check_parsing('{}', 0, { + ast = { + 'DictLiteral:0:0:{', + }, + }, { + hl('Dict', '{'), + hl('Dict', '}'), + }) + check_parsing('{->@a}', 0, { + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Arrow:0:1:->', + children = { + 'Register(name=a):0:3:@a', + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + }) + check_parsing('{->@a+@b}', 0, { + -- 012345678 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Arrow:0:1:->', + children = { + { + 'BinaryPlus:0:5:+', + children = { + 'Register(name=a):0:3:@a', + 'Register(name=b):0:6:@b', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('BinaryPlus', '+'), + hl('Register', '@b'), + hl('Lambda', '}'), + }) + check_parsing('{a->@a}', 0, { + -- 012345678 + ast = { + { + 'Lambda:0:0:{', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + { + 'Arrow:0:2:->', + children = { + 'Register(name=a):0:4:@a', + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + }) + check_parsing('{a,b->@a}', 0, { + -- 012345678 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + 'PlainIdentifier(scope=0,ident=b):0:3:b', + }, + }, + { + 'Arrow:0:4:->', + children = { + 'Register(name=a):0:6:@a', + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + }) + check_parsing('{a,b,c->@a}', 0, { + -- 01234567890 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + { + 'Comma:0:4:,', + children = { + 'PlainIdentifier(scope=0,ident=b):0:3:b', + 'PlainIdentifier(scope=0,ident=c):0:5:c', + }, + }, + }, + }, + { + 'Arrow:0:6:->', + children = { + 'Register(name=a):0:8:@a', + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('Comma', ','), + hl('IdentifierName', 'c'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + }) + check_parsing('{a,b,c,d->@a}', 0, { + -- 0123456789012 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + { + 'Comma:0:4:,', + children = { + 'PlainIdentifier(scope=0,ident=b):0:3:b', + { + 'Comma:0:6:,', + children = { + 'PlainIdentifier(scope=0,ident=c):0:5:c', + 'PlainIdentifier(scope=0,ident=d):0:7:d', + }, + }, + }, + }, + }, + }, + { + 'Arrow:0:8:->', + children = { + 'Register(name=a):0:10:@a', + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('Comma', ','), + hl('IdentifierName', 'c'), + hl('Comma', ','), + hl('IdentifierName', 'd'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + }) + check_parsing('{a,b,c,d,->@a}', 0, { + -- 01234567890123 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + { + 'Comma:0:4:,', + children = { + 'PlainIdentifier(scope=0,ident=b):0:3:b', + { + 'Comma:0:6:,', + children = { + 'PlainIdentifier(scope=0,ident=c):0:5:c', + { + 'Comma:0:8:,', + children = { + 'PlainIdentifier(scope=0,ident=d):0:7:d', + }, + }, + }, + }, + }, + }, + }, + }, + { + 'Arrow:0:9:->', + children = { + 'Register(name=a):0:11:@a', + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('Comma', ','), + hl('IdentifierName', 'c'), + hl('Comma', ','), + hl('IdentifierName', 'd'), + hl('Comma', ','), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + }) + check_parsing('{a,b->{c,d->{e,f->@a}}}', 0, { + -- 01234567890123456789012 + -- 0 1 2 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + 'PlainIdentifier(scope=0,ident=b):0:3:b', + }, + }, + { + 'Arrow:0:4:->', + children = { + { + 'Lambda:0:6:{', + children = { + { + 'Comma:0:8:,', + children = { + 'PlainIdentifier(scope=0,ident=c):0:7:c', + 'PlainIdentifier(scope=0,ident=d):0:9:d', + }, + }, + { + 'Arrow:0:10:->', + children = { + { + 'Lambda:0:12:{', + children = { + { + 'Comma:0:14:,', + children = { + 'PlainIdentifier(scope=0,ident=e):0:13:e', + 'PlainIdentifier(scope=0,ident=f):0:15:f', + }, + }, + { + 'Arrow:0:16:->', + children = { + 'Register(name=a):0:18:@a', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('Arrow', '->'), + hl('Lambda', '{'), + hl('IdentifierName', 'c'), + hl('Comma', ','), + hl('IdentifierName', 'd'), + hl('Arrow', '->'), + hl('Lambda', '{'), + hl('IdentifierName', 'e'), + hl('Comma', ','), + hl('IdentifierName', 'f'), + hl('Arrow', '->'), + hl('Register', '@a'), + hl('Lambda', '}'), + hl('Lambda', '}'), + hl('Lambda', '}'), + }) + check_parsing('{a,b->c,d}', 0, { + -- 0123456789 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + 'PlainIdentifier(scope=0,ident=b):0:3:b', + }, + }, + { + 'Arrow:0:4:->', + children = { + { + 'Comma:0:7:,', + children = { + 'PlainIdentifier(scope=0,ident=c):0:6:c', + 'PlainIdentifier(scope=0,ident=d):0:8:d', + }, + }, + }, + }, + }, + }, + }, + err = { + arg = ',d}', + msg = 'E15: Comma outside of call, lambda or literal: %.*s', + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('Arrow', '->'), + hl('IdentifierName', 'c'), + hl('InvalidComma', ','), + hl('IdentifierName', 'd'), + hl('Lambda', '}'), + }) + check_parsing('a,b,c,d', 0, { + -- 0123456789 + ast = { + { + 'Comma:0:1:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:0:a', + { + 'Comma:0:3:,', + children = { + 'PlainIdentifier(scope=0,ident=b):0:2:b', + { + 'Comma:0:5:,', + children = { + 'PlainIdentifier(scope=0,ident=c):0:4:c', + 'PlainIdentifier(scope=0,ident=d):0:6:d', + }, + }, + }, + }, + }, + }, + }, + err = { + arg = ',b,c,d', + msg = 'E15: Comma outside of call, lambda or literal: %.*s', + }, + }, { + hl('IdentifierName', 'a'), + hl('InvalidComma', ','), + hl('IdentifierName', 'b'), + hl('InvalidComma', ','), + hl('IdentifierName', 'c'), + hl('InvalidComma', ','), + hl('IdentifierName', 'd'), + }) + check_parsing('a,b,c,d,', 0, { + -- 0123456789 + ast = { + { + 'Comma:0:1:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:0:a', + { + 'Comma:0:3:,', + children = { + 'PlainIdentifier(scope=0,ident=b):0:2:b', + { + 'Comma:0:5:,', + children = { + 'PlainIdentifier(scope=0,ident=c):0:4:c', + { + 'Comma:0:7:,', + children = { + 'PlainIdentifier(scope=0,ident=d):0:6:d', + }, + }, + }, + }, + }, + }, + }, + }, + }, + err = { + arg = ',b,c,d,', + msg = 'E15: Comma outside of call, lambda or literal: %.*s', + }, + }, { + hl('IdentifierName', 'a'), + hl('InvalidComma', ','), + hl('IdentifierName', 'b'), + hl('InvalidComma', ','), + hl('IdentifierName', 'c'), + hl('InvalidComma', ','), + hl('IdentifierName', 'd'), + hl('InvalidComma', ','), + }) + check_parsing(',', 0, { + -- 0123456789 + ast = { + { + 'Comma:0:0:,', + children = { + 'Missing:0:0:', + }, + }, + }, + err = { + arg = ',', + msg = 'E15: Expected value, got comma: %.*s', + }, + }, { + hl('InvalidComma', ','), + }) + check_parsing('{,a->@a}', 0, { + -- 0123456789 + ast = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + { + 'Arrow:0:3:->', + children = { + { + 'Comma:0:1:,', + children = { + 'Missing:0:1:', + 'PlainIdentifier(scope=0,ident=a):0:2:a', + }, + }, + 'Register(name=a):0:5:@a', + }, + }, + }, + }, + }, + err = { + arg = ',a->@a}', + msg = 'E15: Expected value, got comma: %.*s', + }, + }, { + hl('Curly', '{'), + hl('InvalidComma', ','), + hl('IdentifierName', 'a'), + hl('InvalidArrow', '->'), + hl('Register', '@a'), + hl('Curly', '}'), + }) + check_parsing('}', 0, { + -- 0123456789 + ast = { + 'UnknownFigure:0:0:', + }, + err = { + arg = '}', + msg = 'E15: Unexpected closing figure brace: %.*s', + }, + }, { + hl('InvalidFigureBrace', '}'), + }) + check_parsing('{->}', 0, { + -- 0123456789 + ast = { + { + 'Lambda:0:0:{', + children = { + 'Arrow:0:1:->', + }, + }, + }, + err = { + arg = '}', + msg = 'E15: Expected value, got closing figure brace: %.*s', + }, + }, { + hl('Lambda', '{'), + hl('Arrow', '->'), + hl('InvalidLambda', '}'), + }) + check_parsing('{a,b}', 0, { + -- 0123456789 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + 'PlainIdentifier(scope=0,ident=b):0:3:b', + }, + }, + }, + }, + }, + err = { + arg = '}', + msg = 'E15: Expected lambda arguments list or arrow: %.*s', + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('IdentifierName', 'b'), + hl('InvalidLambda', '}'), + }) + check_parsing('{a,}', 0, { + -- 0123456789 + ast = { + { + 'Lambda:0:0:{', + children = { + { + 'Comma:0:2:,', + children = { + 'PlainIdentifier(scope=0,ident=a):0:1:a', + }, + }, + }, + }, + }, + err = { + arg = '}', + msg = 'E15: Expected lambda arguments list or arrow: %.*s', + }, + }, { + hl('Lambda', '{'), + hl('IdentifierName', 'a'), + hl('Comma', ','), + hl('InvalidLambda', '}'), + }) + check_parsing('{@a:@b}', 0, { + -- 0123456789 + ast = { + { + 'DictLiteral:0:0:{', + children = { + { + 'Colon:0:3::', + children = { + 'Register(name=a):0:1:@a', + 'Register(name=b):0:4:@b', + }, + }, + }, + }, + }, + }, { + hl('Dict', '{'), + hl('Register', '@a'), + hl('Colon', ':'), + hl('Register', '@b'), + hl('Dict', '}'), + }) + check_parsing('{@a:@b,@c:@d}', 0, { + -- 0123456789012 + -- 0 1 + ast = { + { + 'DictLiteral:0:0:{', + children = { + { + 'Comma:0:6:,', + children = { + { + 'Colon:0:3::', + children = { + 'Register(name=a):0:1:@a', + 'Register(name=b):0:4:@b', + }, + }, + { + 'Colon:0:9::', + children = { + 'Register(name=c):0:7:@c', + 'Register(name=d):0:10:@d', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Dict', '{'), + hl('Register', '@a'), + hl('Colon', ':'), + hl('Register', '@b'), + hl('Comma', ','), + hl('Register', '@c'), + hl('Colon', ':'), + hl('Register', '@d'), + hl('Dict', '}'), + }) + check_parsing('{@a:@b,@c:@d,@e:@f,}', 0, { + -- 01234567890123456789 + -- 0 1 + ast = { + { + 'DictLiteral:0:0:{', + children = { + { + 'Comma:0:6:,', + children = { + { + 'Colon:0:3::', + children = { + 'Register(name=a):0:1:@a', + 'Register(name=b):0:4:@b', + }, + }, + { + 'Comma:0:12:,', + children = { + { + 'Colon:0:9::', + children = { + 'Register(name=c):0:7:@c', + 'Register(name=d):0:10:@d', + }, + }, + { + 'Comma:0:18:,', + children = { + { + 'Colon:0:15::', + children = { + 'Register(name=e):0:13:@e', + 'Register(name=f):0:16:@f', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Dict', '{'), + hl('Register', '@a'), + hl('Colon', ':'), + hl('Register', '@b'), + hl('Comma', ','), + hl('Register', '@c'), + hl('Colon', ':'), + hl('Register', '@d'), + hl('Comma', ','), + hl('Register', '@e'), + hl('Colon', ':'), + hl('Register', '@f'), + hl('Comma', ','), + hl('Dict', '}'), + }) + check_parsing('{@a:@b,@c:@d,@e:@f,@g:}', 0, { + -- 01234567890123456789012 + -- 0 1 2 + ast = { + { + 'DictLiteral:0:0:{', + children = { + { + 'Comma:0:6:,', + children = { + { + 'Colon:0:3::', + children = { + 'Register(name=a):0:1:@a', + 'Register(name=b):0:4:@b', + }, + }, + { + 'Comma:0:12:,', + children = { + { + 'Colon:0:9::', + children = { + 'Register(name=c):0:7:@c', + 'Register(name=d):0:10:@d', + }, + }, + { + 'Comma:0:18:,', + children = { + { + 'Colon:0:15::', + children = { + 'Register(name=e):0:13:@e', + 'Register(name=f):0:16:@f', + }, + }, + { + 'Colon:0:21::', + children = { + 'Register(name=g):0:19:@g', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + err = { + arg = '}', + msg = 'E15: Expected value, got closing figure brace: %.*s', + }, + }, { + hl('Dict', '{'), + hl('Register', '@a'), + hl('Colon', ':'), + hl('Register', '@b'), + hl('Comma', ','), + hl('Register', '@c'), + hl('Colon', ':'), + hl('Register', '@d'), + hl('Comma', ','), + hl('Register', '@e'), + hl('Colon', ':'), + hl('Register', '@f'), + hl('Comma', ','), + hl('Register', '@g'), + hl('Colon', ':'), + hl('InvalidDict', '}'), + }) + check_parsing('{@a:@b,}', 0, { + -- 01234567890123 + -- 0 1 + ast = { + { + 'DictLiteral:0:0:{', + children = { + { + 'Comma:0:6:,', + children = { + { + 'Colon:0:3::', + children = { + 'Register(name=a):0:1:@a', + 'Register(name=b):0:4:@b', + }, + }, + }, + }, + }, + }, + }, + }, { + hl('Dict', '{'), + hl('Register', '@a'), + hl('Colon', ':'), + hl('Register', '@b'), + hl('Comma', ','), + hl('Dict', '}'), + }) + check_parsing('{({f -> g})(@h)(@i)}', 0, { + -- 01234567890123456789 + -- 0 1 + ast = { + { + 'CurlyBracesIdentifier:0:0:{', + children = { + { +