neovim

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

parser_tests.lua (212640B)


      1 local REMOVE_THIS = vim.NIL
      2 
      3 return function(itp, _check_parsing, hl, fmtn)
      4  local function check_parsing(...)
      5    return _check_parsing({ flags = { 0, 1, 2, 3 }, funcname = 'check_parsing' }, ...)
      6  end
      7  local function check_asgn_parsing(...)
      8    return _check_parsing({
      9      flags = { 4, 5, 6, 7 },
     10      funcname = 'check_asgn_parsing',
     11    }, ...)
     12  end
     13  itp('works with + and @a', function()
     14    check_parsing('@a', {
     15      ast = {
     16        'Register(name=a):0:0:@a',
     17      },
     18    }, {
     19      hl('Register', '@a'),
     20    })
     21    check_parsing('+@a', {
     22      ast = {
     23        {
     24          'UnaryPlus:0:0:+',
     25          children = {
     26            'Register(name=a):0:1:@a',
     27          },
     28        },
     29      },
     30    }, {
     31      hl('UnaryPlus', '+'),
     32      hl('Register', '@a'),
     33    })
     34    check_parsing('@a+@b', {
     35      ast = {
     36        {
     37          'BinaryPlus:0:2:+',
     38          children = {
     39            'Register(name=a):0:0:@a',
     40            'Register(name=b):0:3:@b',
     41          },
     42        },
     43      },
     44    }, {
     45      hl('Register', '@a'),
     46      hl('BinaryPlus', '+'),
     47      hl('Register', '@b'),
     48    })
     49    check_parsing('@a+@b+@c', {
     50      ast = {
     51        {
     52          'BinaryPlus:0:5:+',
     53          children = {
     54            {
     55              'BinaryPlus:0:2:+',
     56              children = {
     57                'Register(name=a):0:0:@a',
     58                'Register(name=b):0:3:@b',
     59              },
     60            },
     61            'Register(name=c):0:6:@c',
     62          },
     63        },
     64      },
     65    }, {
     66      hl('Register', '@a'),
     67      hl('BinaryPlus', '+'),
     68      hl('Register', '@b'),
     69      hl('BinaryPlus', '+'),
     70      hl('Register', '@c'),
     71    })
     72    check_parsing('+@a+@b', {
     73      ast = {
     74        {
     75          'BinaryPlus:0:3:+',
     76          children = {
     77            {
     78              'UnaryPlus:0:0:+',
     79              children = {
     80                'Register(name=a):0:1:@a',
     81              },
     82            },
     83            'Register(name=b):0:4:@b',
     84          },
     85        },
     86      },
     87    }, {
     88      hl('UnaryPlus', '+'),
     89      hl('Register', '@a'),
     90      hl('BinaryPlus', '+'),
     91      hl('Register', '@b'),
     92    })
     93    check_parsing('+@a++@b', {
     94      ast = {
     95        {
     96          'BinaryPlus:0:3:+',
     97          children = {
     98            {
     99              'UnaryPlus:0:0:+',
    100              children = {
    101                'Register(name=a):0:1:@a',
    102              },
    103            },
    104            {
    105              'UnaryPlus:0:4:+',
    106              children = {
    107                'Register(name=b):0:5:@b',
    108              },
    109            },
    110          },
    111        },
    112      },
    113    }, {
    114      hl('UnaryPlus', '+'),
    115      hl('Register', '@a'),
    116      hl('BinaryPlus', '+'),
    117      hl('UnaryPlus', '+'),
    118      hl('Register', '@b'),
    119    })
    120    check_parsing('@a@b', {
    121      ast = {
    122        {
    123          'OpMissing:0:2:',
    124          children = {
    125            'Register(name=a):0:0:@a',
    126            'Register(name=b):0:2:@b',
    127          },
    128        },
    129      },
    130      err = {
    131        arg = '@b',
    132        msg = 'E15: Missing operator: %.*s',
    133      },
    134    }, {
    135      hl('Register', '@a'),
    136      hl('InvalidRegister', '@b'),
    137    }, {
    138      [1] = {
    139        ast = {
    140          len = 2,
    141          err = REMOVE_THIS,
    142          ast = {
    143            'Register(name=a):0:0:@a',
    144          },
    145        },
    146        hl_fs = {
    147          [2] = REMOVE_THIS,
    148        },
    149      },
    150    })
    151    check_parsing(' @a \t @b', {
    152      ast = {
    153        {
    154          'OpMissing:0:3:',
    155          children = {
    156            'Register(name=a):0:0: @a',
    157            'Register(name=b):0:3: \t @b',
    158          },
    159        },
    160      },
    161      err = {
    162        arg = '@b',
    163        msg = 'E15: Missing operator: %.*s',
    164      },
    165    }, {
    166      hl('Register', '@a', 1),
    167      hl('InvalidSpacing', ' \t '),
    168      hl('Register', '@b'),
    169    }, {
    170      [1] = {
    171        ast = {
    172          len = 6,
    173          err = REMOVE_THIS,
    174          ast = {
    175            'Register(name=a):0:0: @a',
    176          },
    177        },
    178        hl_fs = {
    179          [2] = REMOVE_THIS,
    180          [3] = REMOVE_THIS,
    181        },
    182      },
    183    })
    184    check_parsing('+', {
    185      ast = {
    186        'UnaryPlus:0:0:+',
    187      },
    188      err = {
    189        arg = '',
    190        msg = 'E15: Expected value, got EOC: %.*s',
    191      },
    192    }, {
    193      hl('UnaryPlus', '+'),
    194    })
    195    check_parsing(' +', {
    196      ast = {
    197        'UnaryPlus:0:0: +',
    198      },
    199      err = {
    200        arg = '',
    201        msg = 'E15: Expected value, got EOC: %.*s',
    202      },
    203    }, {
    204      hl('UnaryPlus', '+', 1),
    205    })
    206    check_parsing('@a+  ', {
    207      ast = {
    208        {
    209          'BinaryPlus:0:2:+',
    210          children = {
    211            'Register(name=a):0:0:@a',
    212          },
    213        },
    214      },
    215      err = {
    216        arg = '',
    217        msg = 'E15: Expected value, got EOC: %.*s',
    218      },
    219    }, {
    220      hl('Register', '@a'),
    221      hl('BinaryPlus', '+'),
    222    })
    223  end)
    224  itp('works with @a, + and parenthesis', function()
    225    check_parsing('(@a)', {
    226      ast = {
    227        {
    228          'Nested:0:0:(',
    229          children = {
    230            'Register(name=a):0:1:@a',
    231          },
    232        },
    233      },
    234    }, {
    235      hl('NestingParenthesis', '('),
    236      hl('Register', '@a'),
    237      hl('NestingParenthesis', ')'),
    238    })
    239    check_parsing('()', {
    240      ast = {
    241        {
    242          'Nested:0:0:(',
    243          children = {
    244            'Missing:0:1:',
    245          },
    246        },
    247      },
    248      err = {
    249        arg = ')',
    250        msg = 'E15: Expected value, got parenthesis: %.*s',
    251      },
    252    }, {
    253      hl('NestingParenthesis', '('),
    254      hl('InvalidNestingParenthesis', ')'),
    255    })
    256    check_parsing(')', {
    257      ast = {
    258        {
    259          'Nested:0:0:',
    260          children = {
    261            'Missing:0:0:',
    262          },
    263        },
    264      },
    265      err = {
    266        arg = ')',
    267        msg = 'E15: Expected value, got parenthesis: %.*s',
    268      },
    269    }, {
    270      hl('InvalidNestingParenthesis', ')'),
    271    })
    272    check_parsing('+)', {
    273      ast = {
    274        {
    275          'Nested:0:1:',
    276          children = {
    277            {
    278              'UnaryPlus:0:0:+',
    279              children = {
    280                'Missing:0:1:',
    281              },
    282            },
    283          },
    284        },
    285      },
    286      err = {
    287        arg = ')',
    288        msg = 'E15: Expected value, got parenthesis: %.*s',
    289      },
    290    }, {
    291      hl('UnaryPlus', '+'),
    292      hl('InvalidNestingParenthesis', ')'),
    293    })
    294    check_parsing('+@a(@b)', {
    295      ast = {
    296        {
    297          'UnaryPlus:0:0:+',
    298          children = {
    299            {
    300              'Call:0:3:(',
    301              children = {
    302                'Register(name=a):0:1:@a',
    303                'Register(name=b):0:4:@b',
    304              },
    305            },
    306          },
    307        },
    308      },
    309    }, {
    310      hl('UnaryPlus', '+'),
    311      hl('Register', '@a'),
    312      hl('CallingParenthesis', '('),
    313      hl('Register', '@b'),
    314      hl('CallingParenthesis', ')'),
    315    })
    316    check_parsing('@a+@b(@c)', {
    317      ast = {
    318        {
    319          'BinaryPlus:0:2:+',
    320          children = {
    321            'Register(name=a):0:0:@a',
    322            {
    323              'Call:0:5:(',
    324              children = {
    325                'Register(name=b):0:3:@b',
    326                'Register(name=c):0:6:@c',
    327              },
    328            },
    329          },
    330        },
    331      },
    332    }, {
    333      hl('Register', '@a'),
    334      hl('BinaryPlus', '+'),
    335      hl('Register', '@b'),
    336      hl('CallingParenthesis', '('),
    337      hl('Register', '@c'),
    338      hl('CallingParenthesis', ')'),
    339    })
    340    check_parsing('@a()', {
    341      ast = {
    342        {
    343          'Call:0:2:(',
    344          children = {
    345            'Register(name=a):0:0:@a',
    346          },
    347        },
    348      },
    349    }, {
    350      hl('Register', '@a'),
    351      hl('CallingParenthesis', '('),
    352      hl('CallingParenthesis', ')'),
    353    })
    354    check_parsing('@a ()', {
    355      ast = {
    356        {
    357          'OpMissing:0:2:',
    358          children = {
    359            'Register(name=a):0:0:@a',
    360            {
    361              'Nested:0:2: (',
    362              children = {
    363                'Missing:0:4:',
    364              },
    365            },
    366          },
    367        },
    368      },
    369      err = {
    370        arg = '()',
    371        msg = 'E15: Missing operator: %.*s',
    372      },
    373    }, {
    374      hl('Register', '@a'),
    375      hl('InvalidSpacing', ' '),
    376      hl('NestingParenthesis', '('),
    377      hl('InvalidNestingParenthesis', ')'),
    378    }, {
    379      [1] = {
    380        ast = {
    381          len = 3,
    382          err = REMOVE_THIS,
    383          ast = {
    384            'Register(name=a):0:0:@a',
    385          },
    386        },
    387        hl_fs = {
    388          [2] = REMOVE_THIS,
    389          [3] = REMOVE_THIS,
    390          [4] = REMOVE_THIS,
    391        },
    392      },
    393    })
    394    check_parsing('@a + (@b)', {
    395      ast = {
    396        {
    397          'BinaryPlus:0:2: +',
    398          children = {
    399            'Register(name=a):0:0:@a',
    400            {
    401              'Nested:0:4: (',
    402              children = {
    403                'Register(name=b):0:6:@b',
    404              },
    405            },
    406          },
    407        },
    408      },
    409    }, {
    410      hl('Register', '@a'),
    411      hl('BinaryPlus', '+', 1),
    412      hl('NestingParenthesis', '(', 1),
    413      hl('Register', '@b'),
    414      hl('NestingParenthesis', ')'),
    415    })
    416    check_parsing('@a + (+@b)', {
    417      ast = {
    418        {
    419          'BinaryPlus:0:2: +',
    420          children = {
    421            'Register(name=a):0:0:@a',
    422            {
    423              'Nested:0:4: (',
    424              children = {
    425                {
    426                  'UnaryPlus:0:6:+',
    427                  children = {
    428                    'Register(name=b):0:7:@b',
    429                  },
    430                },
    431              },
    432            },
    433          },
    434        },
    435      },
    436    }, {
    437      hl('Register', '@a'),
    438      hl('BinaryPlus', '+', 1),
    439      hl('NestingParenthesis', '(', 1),
    440      hl('UnaryPlus', '+'),
    441      hl('Register', '@b'),
    442      hl('NestingParenthesis', ')'),
    443    })
    444    check_parsing('@a + (@b + @c)', {
    445      ast = {
    446        {
    447          'BinaryPlus:0:2: +',
    448          children = {
    449            'Register(name=a):0:0:@a',
    450            {
    451              'Nested:0:4: (',
    452              children = {
    453                {
    454                  'BinaryPlus:0:8: +',
    455                  children = {
    456                    'Register(name=b):0:6:@b',
    457                    'Register(name=c):0:10: @c',
    458                  },
    459                },
    460              },
    461            },
    462          },
    463        },
    464      },
    465    }, {
    466      hl('Register', '@a'),
    467      hl('BinaryPlus', '+', 1),
    468      hl('NestingParenthesis', '(', 1),
    469      hl('Register', '@b'),
    470      hl('BinaryPlus', '+', 1),
    471      hl('Register', '@c', 1),
    472      hl('NestingParenthesis', ')'),
    473    })
    474    check_parsing('(@a)+@b', {
    475      ast = {
    476        {
    477          'BinaryPlus:0:4:+',
    478          children = {
    479            {
    480              'Nested:0:0:(',
    481              children = {
    482                'Register(name=a):0:1:@a',
    483              },
    484            },
    485            'Register(name=b):0:5:@b',
    486          },
    487        },
    488      },
    489    }, {
    490      hl('NestingParenthesis', '('),
    491      hl('Register', '@a'),
    492      hl('NestingParenthesis', ')'),
    493      hl('BinaryPlus', '+'),
    494      hl('Register', '@b'),
    495    })
    496    check_parsing('@a+(@b)(@c)', {
    497      --           01234567890
    498      ast = {
    499        {
    500          'BinaryPlus:0:2:+',
    501          children = {
    502            'Register(name=a):0:0:@a',
    503            {
    504              'Call:0:7:(',
    505              children = {
    506                {
    507                  'Nested:0:3:(',
    508                  children = { 'Register(name=b):0:4:@b' },
    509                },
    510                'Register(name=c):0:8:@c',
    511              },
    512            },
    513          },
    514        },
    515      },
    516    }, {
    517      hl('Register', '@a'),
    518      hl('BinaryPlus', '+'),
    519      hl('NestingParenthesis', '('),
    520      hl('Register', '@b'),
    521      hl('NestingParenthesis', ')'),
    522      hl('CallingParenthesis', '('),
    523      hl('Register', '@c'),
    524      hl('CallingParenthesis', ')'),
    525    })
    526    check_parsing('@a+((@b))(@c)', {
    527      --           01234567890123456890123456789
    528      --           0         1        2
    529      ast = {
    530        {
    531          'BinaryPlus:0:2:+',
    532          children = {
    533            'Register(name=a):0:0:@a',
    534            {
    535              'Call:0:9:(',
    536              children = {
    537                {
    538                  'Nested:0:3:(',
    539                  children = {
    540                    {
    541                      'Nested:0:4:(',
    542                      children = { 'Register(name=b):0:5:@b' },
    543                    },
    544                  },
    545                },
    546                'Register(name=c):0:10:@c',
    547              },
    548            },
    549          },
    550        },
    551      },
    552    }, {
    553      hl('Register', '@a'),
    554      hl('BinaryPlus', '+'),
    555      hl('NestingParenthesis', '('),
    556      hl('NestingParenthesis', '('),
    557      hl('Register', '@b'),
    558      hl('NestingParenthesis', ')'),
    559      hl('NestingParenthesis', ')'),
    560      hl('CallingParenthesis', '('),
    561      hl('Register', '@c'),
    562      hl('CallingParenthesis', ')'),
    563    })
    564    check_parsing('@a+((@b))+@c', {
    565      --           01234567890123456890123456789
    566      --           0         1        2
    567      ast = {
    568        {
    569          'BinaryPlus:0:9:+',
    570          children = {
    571            {
    572              'BinaryPlus:0:2:+',
    573              children = {
    574                'Register(name=a):0:0:@a',
    575                {
    576                  'Nested:0:3:(',
    577                  children = {
    578                    {
    579                      'Nested:0:4:(',
    580                      children = { 'Register(name=b):0:5:@b' },
    581                    },
    582                  },
    583                },
    584              },
    585            },
    586            'Register(name=c):0:10:@c',
    587          },
    588        },
    589      },
    590    }, {
    591      hl('Register', '@a'),
    592      hl('BinaryPlus', '+'),
    593      hl('NestingParenthesis', '('),
    594      hl('NestingParenthesis', '('),
    595      hl('Register', '@b'),
    596      hl('NestingParenthesis', ')'),
    597      hl('NestingParenthesis', ')'),
    598      hl('BinaryPlus', '+'),
    599      hl('Register', '@c'),
    600    })
    601    check_parsing('@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
    602       | | | | | |   | |  ||  | | ||  | | ||| ||   ||  ||   ||
    603       000000000011111111112222222222333333333344444444445555555
    604       012345678901234567890123456789012345678901234567890123456
    605      ]]
    606      ast = {
    607        {
    608          'BinaryPlus:0:31: +',
    609          children = {
    610            {
    611              'BinaryPlus:0:23: +',
    612              children = {
    613                {
    614                  'BinaryPlus:0:14: +',
    615                  children = {
    616                    {
    617                      'BinaryPlus:0:2: +',
    618                      children = {
    619                        'Register(name=a):0:0:@a',
    620                        {
    621                          'Nested:0:4: (',
    622                          children = {
    623                            {
    624                              'BinaryPlus:0:8: +',
    625                              children = {
    626                                'Register(name=b):0:6:@b',
    627                                'Register(name=c):0:10: @c',
    628                              },
    629                            },
    630                          },
    631                        },
    632                      },
    633                    },
    634                    {
    635                      'Call:0:19:(',
    636                      children = {
    637                        'Register(name=d):0:16: @d',
    638                        'Register(name=e):0:20:@e',
    639                      },
    640                    },
    641                  },
    642                },
    643                {
    644                  'Nested:0:25: (',
    645                  children = {
    646                    {
    647                      'UnaryPlus:0:27:+',
    648                      children = {
    649                        'Register(name=f):0:28:@f',
    650                      },
    651                    },
    652                  },
    653                },
    654              },
    655            },
    656            {
    657              'Call:0:53:(',
    658              children = {
    659                {
    660                  'Nested:0:33: (',
    661                  children = {
    662                    {
    663                      'Call:0:48:(',
    664                      children = {
    665                        {
    666                          'Call:0:44:(',
    667                          children = {
    668                            {
    669                              'Nested:0:35:(',
    670                              children = {
    671                                {
    672                                  'UnaryPlus:0:36:+',
    673                                  children = {
    674                                    {
    675                                      'Call:0:39:(',
    676                                      children = {
    677                                        'Register(name=g):0:37:@g',
    678                                        'Register(name=h):0:40:@h',
    679                                      },
    680                                    },
    681                                  },
    682                                },
    683                              },
    684                            },
    685                            'Register(name=j):0:45:@j',
    686                          },
    687                        },
    688                        'Register(name=k):0:49:@k',
    689                      },
    690                    },
    691                  },
    692                },
    693                'Register(name=l):0:54:@l',
    694              },
    695            },
    696          },
    697        },
    698      },
    699    }, {
    700      hl('Register', '@a'),
    701      hl('BinaryPlus', '+', 1),
    702      hl('NestingParenthesis', '(', 1),
    703      hl('Register', '@b'),
    704      hl('BinaryPlus', '+', 1),
    705      hl('Register', '@c', 1),
    706      hl('NestingParenthesis', ')'),
    707      hl('BinaryPlus', '+', 1),
    708      hl('Register', '@d', 1),
    709      hl('CallingParenthesis', '('),
    710      hl('Register', '@e'),
    711      hl('CallingParenthesis', ')'),
    712      hl('BinaryPlus', '+', 1),
    713      hl('NestingParenthesis', '(', 1),
    714      hl('UnaryPlus', '+'),
    715      hl('Register', '@f'),
    716      hl('NestingParenthesis', ')'),
    717      hl('BinaryPlus', '+', 1),
    718      hl('NestingParenthesis', '(', 1),
    719      hl('NestingParenthesis', '('),
    720      hl('UnaryPlus', '+'),
    721      hl('Register', '@g'),
    722      hl('CallingParenthesis', '('),
    723      hl('Register', '@h'),
    724      hl('CallingParenthesis', ')'),
    725      hl('NestingParenthesis', ')'),
    726      hl('CallingParenthesis', '('),
    727      hl('Register', '@j'),
    728      hl('CallingParenthesis', ')'),
    729      hl('CallingParenthesis', '('),
    730      hl('Register', '@k'),
    731      hl('CallingParenthesis', ')'),
    732      hl('NestingParenthesis', ')'),
    733      hl('CallingParenthesis', '('),
    734      hl('Register', '@l'),
    735      hl('CallingParenthesis', ')'),
    736    })
    737    check_parsing('@a)', {
    738      --           012
    739      ast = {
    740        {
    741          'Nested:0:2:',
    742          children = {
    743            'Register(name=a):0:0:@a',
    744          },
    745        },
    746      },
    747      err = {
    748        arg = ')',
    749        msg = 'E15: Unexpected closing parenthesis: %.*s',
    750      },
    751    }, {
    752      hl('Register', '@a'),
    753      hl('InvalidNestingParenthesis', ')'),
    754    })
    755    check_parsing('(@a', {
    756      --           012
    757      ast = {
    758        {
    759          'Nested:0:0:(',
    760          children = {
    761            'Register(name=a):0:1:@a',
    762          },
    763        },
    764      },
    765      err = {
    766        arg = '(@a',
    767        msg = 'E110: Missing closing parenthesis for nested expression: %.*s',
    768      },
    769    }, {
    770      hl('NestingParenthesis', '('),
    771      hl('Register', '@a'),
    772    })
    773    check_parsing('@a(@b', {
    774      --           01234
    775      ast = {
    776        {
    777          'Call:0:2:(',
    778          children = {
    779            'Register(name=a):0:0:@a',
    780            'Register(name=b):0:3:@b',
    781          },
    782        },
    783      },
    784      err = {
    785        arg = '(@b',
    786        msg = 'E116: Missing closing parenthesis for function call: %.*s',
    787      },
    788    }, {
    789      hl('Register', '@a'),
    790      hl('CallingParenthesis', '('),
    791      hl('Register', '@b'),
    792    })
    793    check_parsing('@a(@b, @c, @d, @e)', {
    794      --           012345678901234567
    795      --           0         1
    796      ast = {
    797        {
    798          'Call:0:2:(',
    799          children = {
    800            'Register(name=a):0:0:@a',
    801            {
    802              'Comma:0:5:,',
    803              children = {
    804                'Register(name=b):0:3:@b',
    805                {
    806                  'Comma:0:9:,',
    807                  children = {
    808                    'Register(name=c):0:6: @c',
    809                    {
    810                      'Comma:0:13:,',
    811                      children = {
    812                        'Register(name=d):0:10: @d',
    813                        'Register(name=e):0:14: @e',
    814                      },
    815                    },
    816                  },
    817                },
    818              },
    819            },
    820          },
    821        },
    822      },
    823    }, {
    824      hl('Register', '@a'),
    825      hl('CallingParenthesis', '('),
    826      hl('Register', '@b'),
    827      hl('Comma', ','),
    828      hl('Register', '@c', 1),
    829      hl('Comma', ','),
    830      hl('Register', '@d', 1),
    831      hl('Comma', ','),
    832      hl('Register', '@e', 1),
    833      hl('CallingParenthesis', ')'),
    834    })
    835    check_parsing('@a(@b(@c))', {
    836      --           01234567890123456789012345678901234567
    837      --           0         1         2         3
    838      ast = {
    839        {
    840          'Call:0:2:(',
    841          children = {
    842            'Register(name=a):0:0:@a',
    843            {
    844              'Call:0:5:(',
    845              children = {
    846                'Register(name=b):0:3:@b',
    847                'Register(name=c):0:6:@c',
    848              },
    849            },
    850          },
    851        },
    852      },
    853    }, {
    854      hl('Register', '@a'),
    855      hl('CallingParenthesis', '('),
    856      hl('Register', '@b'),
    857      hl('CallingParenthesis', '('),
    858      hl('Register', '@c'),
    859      hl('CallingParenthesis', ')'),
    860      hl('CallingParenthesis', ')'),
    861    })
    862    check_parsing('@a(@b(@c(@d(@e), @f(@g(@h), @i(@j)))))', {
    863      --           01234567890123456789012345678901234567
    864      --           0         1         2         3
    865      ast = {
    866        {
    867          'Call:0:2:(',
    868          children = {
    869            'Register(name=a):0:0:@a',
    870            {
    871              'Call:0:5:(',
    872              children = {
    873                'Register(name=b):0:3:@b',
    874                {
    875                  'Call:0:8:(',
    876                  children = {
    877                    'Register(name=c):0:6:@c',
    878                    {
    879                      'Comma:0:15:,',
    880                      children = {
    881                        {
    882                          'Call:0:11:(',
    883                          children = {
    884                            'Register(name=d):0:9:@d',
    885                            'Register(name=e):0:12:@e',
    886                          },
    887                        },
    888                        {
    889                          'Call:0:19:(',
    890                          children = {
    891                            'Register(name=f):0:16: @f',
    892                            {
    893                              'Comma:0:26:,',
    894                              children = {
    895                                {
    896                                  'Call:0:22:(',
    897                                  children = {
    898                                    'Register(name=g):0:20:@g',
    899                                    'Register(name=h):0:23:@h',
    900                                  },
    901                                },
    902                                {
    903                                  'Call:0:30:(',
    904                                  children = {
    905                                    'Register(name=i):0:27: @i',
    906                                    'Register(name=j):0:31:@j',
    907                                  },
    908                                },
    909                              },
    910                            },
    911                          },
    912                        },
    913                      },
    914                    },
    915                  },
    916                },
    917              },
    918            },
    919          },
    920        },
    921      },
    922    }, {
    923      hl('Register', '@a'),
    924      hl('CallingParenthesis', '('),
    925      hl('Register', '@b'),
    926      hl('CallingParenthesis', '('),
    927      hl('Register', '@c'),
    928      hl('CallingParenthesis', '('),
    929      hl('Register', '@d'),
    930      hl('CallingParenthesis', '('),
    931      hl('Register', '@e'),
    932      hl('CallingParenthesis', ')'),
    933      hl('Comma', ','),
    934      hl('Register', '@f', 1),
    935      hl('CallingParenthesis', '('),
    936      hl('Register', '@g'),
    937      hl('CallingParenthesis', '('),
    938      hl('Register', '@h'),
    939      hl('CallingParenthesis', ')'),
    940      hl('Comma', ','),
    941      hl('Register', '@i', 1),
    942      hl('CallingParenthesis', '('),
    943      hl('Register', '@j'),
    944      hl('CallingParenthesis', ')'),
    945      hl('CallingParenthesis', ')'),
    946      hl('CallingParenthesis', ')'),
    947      hl('CallingParenthesis', ')'),
    948      hl('CallingParenthesis', ')'),
    949    })
    950    check_parsing('()()', {
    951      --           0123
    952      ast = {
    953        {
    954          'Call:0:2:(',
    955          children = {
    956            {
    957              'Nested:0:0:(',
    958              children = {
    959                'Missing:0:1:',
    960              },
    961            },
    962          },
    963        },
    964      },
    965      err = {
    966        arg = ')()',
    967        msg = 'E15: Expected value, got parenthesis: %.*s',
    968      },
    969    }, {
    970      hl('NestingParenthesis', '('),
    971      hl('InvalidNestingParenthesis', ')'),
    972      hl('CallingParenthesis', '('),
    973      hl('CallingParenthesis', ')'),
    974    })
    975    check_parsing('(@a)()', {
    976      --           012345
    977      ast = {
    978        {
    979          'Call:0:4:(',
    980          children = {
    981            {
    982              'Nested:0:0:(',
    983              children = {
    984                'Register(name=a):0:1:@a',
    985              },
    986            },
    987          },
    988        },
    989      },
    990    }, {
    991      hl('NestingParenthesis', '('),
    992      hl('Register', '@a'),
    993      hl('NestingParenthesis', ')'),
    994      hl('CallingParenthesis', '('),
    995      hl('CallingParenthesis', ')'),
    996    })
    997    check_parsing('(@a)(@b)', {
    998      --           01234567
    999      ast = {
   1000        {
   1001          'Call:0:4:(',
   1002          children = {
   1003            {
   1004              'Nested:0:0:(',
   1005              children = {
   1006                'Register(name=a):0:1:@a',
   1007              },
   1008            },
   1009            'Register(name=b):0:5:@b',
   1010          },
   1011        },
   1012      },
   1013    }, {
   1014      hl('NestingParenthesis', '('),
   1015      hl('Register', '@a'),
   1016      hl('NestingParenthesis', ')'),
   1017      hl('CallingParenthesis', '('),
   1018      hl('Register', '@b'),
   1019      hl('CallingParenthesis', ')'),
   1020    })
   1021    check_parsing('(@a) (@b)', {
   1022      --           012345678
   1023      ast = {
   1024        {
   1025          'OpMissing:0:4:',
   1026          children = {
   1027            {
   1028              'Nested:0:0:(',
   1029              children = {
   1030                'Register(name=a):0:1:@a',
   1031              },
   1032            },
   1033            {
   1034              'Nested:0:4: (',
   1035              children = {
   1036                'Register(name=b):0:6:@b',
   1037              },
   1038            },
   1039          },
   1040        },
   1041      },
   1042      err = {
   1043        arg = '(@b)',
   1044        msg = 'E15: Missing operator: %.*s',
   1045      },
   1046    }, {
   1047      hl('NestingParenthesis', '('),
   1048      hl('Register', '@a'),
   1049      hl('NestingParenthesis', ')'),
   1050      hl('InvalidSpacing', ' '),
   1051      hl('NestingParenthesis', '('),
   1052      hl('Register', '@b'),
   1053      hl('NestingParenthesis', ')'),
   1054    }, {
   1055      [1] = {
   1056        ast = {
   1057          len = 5,
   1058          ast = {
   1059            {
   1060              'Nested:0:0:(',
   1061              children = {
   1062                'Register(name=a):0:1:@a',
   1063                REMOVE_THIS,
   1064              },
   1065            },
   1066          },
   1067          err = REMOVE_THIS,
   1068        },
   1069        hl_fs = {
   1070          [4] = REMOVE_THIS,
   1071          [5] = REMOVE_THIS,
   1072          [6] = REMOVE_THIS,
   1073          [7] = REMOVE_THIS,
   1074        },
   1075      },
   1076    })
   1077  end)
   1078  itp('works with variable names, including curly braces ones', function()
   1079    check_parsing('var', {
   1080      ast = {
   1081        'PlainIdentifier(scope=0,ident=var):0:0:var',
   1082      },
   1083    }, {
   1084      hl('IdentifierName', 'var'),
   1085    })
   1086    check_parsing('g:var', {
   1087      ast = {
   1088        'PlainIdentifier(scope=g,ident=var):0:0:g:var',
   1089      },
   1090    }, {
   1091      hl('IdentifierScope', 'g'),
   1092      hl('IdentifierScopeDelimiter', ':'),
   1093      hl('IdentifierName', 'var'),
   1094    })
   1095    check_parsing('g:', {
   1096      ast = {
   1097        'PlainIdentifier(scope=g,ident=):0:0:g:',
   1098      },
   1099    }, {
   1100      hl('IdentifierScope', 'g'),
   1101      hl('IdentifierScopeDelimiter', ':'),
   1102    })
   1103    check_parsing('{a}', {
   1104      --           012
   1105      ast = {
   1106        {
   1107          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1108          children = {
   1109            'PlainIdentifier(scope=0,ident=a):0:1:a',
   1110          },
   1111        },
   1112      },
   1113    }, {
   1114      hl('Curly', '{'),
   1115      hl('IdentifierName', 'a'),
   1116      hl('Curly', '}'),
   1117    })
   1118    check_parsing('{a:b}', {
   1119      --           012
   1120      ast = {
   1121        {
   1122          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1123          children = {
   1124            'PlainIdentifier(scope=a,ident=b):0:1:a:b',
   1125          },
   1126        },
   1127      },
   1128    }, {
   1129      hl('Curly', '{'),
   1130      hl('IdentifierScope', 'a'),
   1131      hl('IdentifierScopeDelimiter', ':'),
   1132      hl('IdentifierName', 'b'),
   1133      hl('Curly', '}'),
   1134    })
   1135    check_parsing('{a:@b}', {
   1136      --           012345
   1137      ast = {
   1138        {
   1139          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1140          children = {
   1141            {
   1142              'OpMissing:0:3:',
   1143              children = {
   1144                'PlainIdentifier(scope=a,ident=):0:1:a:',
   1145                'Register(name=b):0:3:@b',
   1146              },
   1147            },
   1148          },
   1149        },
   1150      },
   1151      err = {
   1152        arg = '@b}',
   1153        msg = 'E15: Missing operator: %.*s',
   1154      },
   1155    }, {
   1156      hl('Curly', '{'),
   1157      hl('IdentifierScope', 'a'),
   1158      hl('IdentifierScopeDelimiter', ':'),
   1159      hl('InvalidRegister', '@b'),
   1160      hl('Curly', '}'),
   1161    })
   1162    check_parsing('{@a}', {
   1163      ast = {
   1164        {
   1165          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1166          children = {
   1167            'Register(name=a):0:1:@a',
   1168          },
   1169        },
   1170      },
   1171    }, {
   1172      hl('Curly', '{'),
   1173      hl('Register', '@a'),
   1174      hl('Curly', '}'),
   1175    })
   1176    check_parsing('{@a}{@b}', {
   1177      --           01234567
   1178      ast = {
   1179        {
   1180          'ComplexIdentifier:0:4:',
   1181          children = {
   1182            {
   1183              fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1184              children = {
   1185                'Register(name=a):0:1:@a',
   1186              },
   1187            },
   1188            {
   1189              fmtn('CurlyBracesIdentifier', '--i', ':0:4:{'),
   1190              children = {
   1191                'Register(name=b):0:5:@b',
   1192              },
   1193            },
   1194          },
   1195        },
   1196      },
   1197    }, {
   1198      hl('Curly', '{'),
   1199      hl('Register', '@a'),
   1200      hl('Curly', '}'),
   1201      hl('Curly', '{'),
   1202      hl('Register', '@b'),
   1203      hl('Curly', '}'),
   1204    })
   1205    check_parsing('g:{@a}', {
   1206      --           01234567
   1207      ast = {
   1208        {
   1209          'ComplexIdentifier:0:2:',
   1210          children = {
   1211            'PlainIdentifier(scope=g,ident=):0:0:g:',
   1212            {
   1213              fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   1214              children = {
   1215                'Register(name=a):0:3:@a',
   1216              },
   1217            },
   1218          },
   1219        },
   1220      },
   1221    }, {
   1222      hl('IdentifierScope', 'g'),
   1223      hl('IdentifierScopeDelimiter', ':'),
   1224      hl('Curly', '{'),
   1225      hl('Register', '@a'),
   1226      hl('Curly', '}'),
   1227    })
   1228    check_parsing('{@a}_test', {
   1229      --           012345678
   1230      ast = {
   1231        {
   1232          'ComplexIdentifier:0:4:',
   1233          children = {
   1234            {
   1235              fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1236              children = {
   1237                'Register(name=a):0:1:@a',
   1238              },
   1239            },
   1240            'PlainIdentifier(scope=0,ident=_test):0:4:_test',
   1241          },
   1242        },
   1243      },
   1244    }, {
   1245      hl('Curly', '{'),
   1246      hl('Register', '@a'),
   1247      hl('Curly', '}'),
   1248      hl('IdentifierName', '_test'),
   1249    })
   1250    check_parsing('g:{@a}_test', {
   1251      --           01234567890
   1252      ast = {
   1253        {
   1254          'ComplexIdentifier:0:2:',
   1255          children = {
   1256            'PlainIdentifier(scope=g,ident=):0:0:g:',
   1257            {
   1258              'ComplexIdentifier:0:6:',
   1259              children = {
   1260                {
   1261                  fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   1262                  children = {
   1263                    'Register(name=a):0:3:@a',
   1264                  },
   1265                },
   1266                'PlainIdentifier(scope=0,ident=_test):0:6:_test',
   1267              },
   1268            },
   1269          },
   1270        },
   1271      },
   1272    }, {
   1273      hl('IdentifierScope', 'g'),
   1274      hl('IdentifierScopeDelimiter', ':'),
   1275      hl('Curly', '{'),
   1276      hl('Register', '@a'),
   1277      hl('Curly', '}'),
   1278      hl('IdentifierName', '_test'),
   1279    })
   1280    check_parsing('g:{@a}_test()', {
   1281      --           0123456789012
   1282      ast = {
   1283        {
   1284          'Call:0:11:(',
   1285          children = {
   1286            {
   1287              'ComplexIdentifier:0:2:',
   1288              children = {
   1289                'PlainIdentifier(scope=g,ident=):0:0:g:',
   1290                {
   1291                  'ComplexIdentifier:0:6:',
   1292                  children = {
   1293                    {
   1294                      fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   1295                      children = {
   1296                        'Register(name=a):0:3:@a',
   1297                      },
   1298                    },
   1299                    'PlainIdentifier(scope=0,ident=_test):0:6:_test',
   1300                  },
   1301                },
   1302              },
   1303            },
   1304          },
   1305        },
   1306      },
   1307    }, {
   1308      hl('IdentifierScope', 'g'),
   1309      hl('IdentifierScopeDelimiter', ':'),
   1310      hl('Curly', '{'),
   1311      hl('Register', '@a'),
   1312      hl('Curly', '}'),
   1313      hl('IdentifierName', '_test'),
   1314      hl('CallingParenthesis', '('),
   1315      hl('CallingParenthesis', ')'),
   1316    })
   1317    check_parsing('{@a} ()', {
   1318      --           0123456789012
   1319      ast = {
   1320        {
   1321          'Call:0:4: (',
   1322          children = {
   1323            {
   1324              fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1325              children = {
   1326                'Register(name=a):0:1:@a',
   1327              },
   1328            },
   1329          },
   1330        },
   1331      },
   1332    }, {
   1333      hl('Curly', '{'),
   1334      hl('Register', '@a'),
   1335      hl('Curly', '}'),
   1336      hl('CallingParenthesis', '(', 1),
   1337      hl('CallingParenthesis', ')'),
   1338    })
   1339    check_parsing('g:{@a} ()', {
   1340      --           0123456789012
   1341      ast = {
   1342        {
   1343          'Call:0:6: (',
   1344          children = {
   1345            {
   1346              'ComplexIdentifier:0:2:',
   1347              children = {
   1348                'PlainIdentifier(scope=g,ident=):0:0:g:',
   1349                {
   1350                  fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   1351                  children = {
   1352                    'Register(name=a):0:3:@a',
   1353                  },
   1354                },
   1355              },
   1356            },
   1357          },
   1358        },
   1359      },
   1360    }, {
   1361      hl('IdentifierScope', 'g'),
   1362      hl('IdentifierScopeDelimiter', ':'),
   1363      hl('Curly', '{'),
   1364      hl('Register', '@a'),
   1365      hl('Curly', '}'),
   1366      hl('CallingParenthesis', '(', 1),
   1367      hl('CallingParenthesis', ')'),
   1368    })
   1369    check_parsing('{@a', {
   1370      --           012
   1371      ast = {
   1372        {
   1373          fmtn('UnknownFigure', '-di', ':0:0:{'),
   1374          children = {
   1375            'Register(name=a):0:1:@a',
   1376          },
   1377        },
   1378      },
   1379      err = {
   1380        arg = '{@a',
   1381        msg = 'E15: Missing closing figure brace: %.*s',
   1382      },
   1383    }, {
   1384      hl('FigureBrace', '{'),
   1385      hl('Register', '@a'),
   1386    })
   1387    check_parsing('a ()', {
   1388      --           0123
   1389      ast = {
   1390        {
   1391          'Call:0:1: (',
   1392          children = {
   1393            'PlainIdentifier(scope=0,ident=a):0:0:a',
   1394          },
   1395        },
   1396      },
   1397    }, {
   1398      hl('IdentifierName', 'a'),
   1399      hl('CallingParenthesis', '(', 1),
   1400      hl('CallingParenthesis', ')'),
   1401    })
   1402  end)
   1403  itp('works with lambdas and dictionaries', function()
   1404    check_parsing('{}', {
   1405      ast = {
   1406        fmtn('DictLiteral', '-di', ':0:0:{'),
   1407      },
   1408    }, {
   1409      hl('Dict', '{'),
   1410      hl('Dict', '}'),
   1411    })
   1412    check_parsing('{->@a}', {
   1413      ast = {
   1414        {
   1415          fmtn('Lambda', '\\di', ':0:0:{'),
   1416          children = {
   1417            {
   1418              'Arrow:0:1:->',
   1419              children = {
   1420                'Register(name=a):0:3:@a',
   1421              },
   1422            },
   1423          },
   1424        },
   1425      },
   1426    }, {
   1427      hl('Lambda', '{'),
   1428      hl('Arrow', '->'),
   1429      hl('Register', '@a'),
   1430      hl('Lambda', '}'),
   1431    })
   1432    check_parsing('{->@a+@b}', {
   1433      --           012345678
   1434      ast = {
   1435        {
   1436          fmtn('Lambda', '\\di', ':0:0:{'),
   1437          children = {
   1438            {
   1439              'Arrow:0:1:->',
   1440              children = {
   1441                {
   1442                  'BinaryPlus:0:5:+',
   1443                  children = {
   1444                    'Register(name=a):0:3:@a',
   1445                    'Register(name=b):0:6:@b',
   1446                  },
   1447                },
   1448              },
   1449            },
   1450          },
   1451        },
   1452      },
   1453    }, {
   1454      hl('Lambda', '{'),
   1455      hl('Arrow', '->'),
   1456      hl('Register', '@a'),
   1457      hl('BinaryPlus', '+'),
   1458      hl('Register', '@b'),
   1459      hl('Lambda', '}'),
   1460    })
   1461    check_parsing('{a->@a}', {
   1462      --           012345678
   1463      ast = {
   1464        {
   1465          fmtn('Lambda', '\\di', ':0:0:{'),
   1466          children = {
   1467            'PlainIdentifier(scope=0,ident=a):0:1:a',
   1468            {
   1469              'Arrow:0:2:->',
   1470              children = {
   1471                'Register(name=a):0:4:@a',
   1472              },
   1473            },
   1474          },
   1475        },
   1476      },
   1477    }, {
   1478      hl('Lambda', '{'),
   1479      hl('IdentifierName', 'a'),
   1480      hl('Arrow', '->'),
   1481      hl('Register', '@a'),
   1482      hl('Lambda', '}'),
   1483    })
   1484    check_parsing('{a,b->@a}', {
   1485      --           012345678
   1486      ast = {
   1487        {
   1488          fmtn('Lambda', '\\di', ':0:0:{'),
   1489          children = {
   1490            {
   1491              'Comma:0:2:,',
   1492              children = {
   1493                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1494                'PlainIdentifier(scope=0,ident=b):0:3:b',
   1495              },
   1496            },
   1497            {
   1498              'Arrow:0:4:->',
   1499              children = {
   1500                'Register(name=a):0:6:@a',
   1501              },
   1502            },
   1503          },
   1504        },
   1505      },
   1506    }, {
   1507      hl('Lambda', '{'),
   1508      hl('IdentifierName', 'a'),
   1509      hl('Comma', ','),
   1510      hl('IdentifierName', 'b'),
   1511      hl('Arrow', '->'),
   1512      hl('Register', '@a'),
   1513      hl('Lambda', '}'),
   1514    })
   1515    check_parsing('{a,b,c->@a}', {
   1516      --           01234567890
   1517      ast = {
   1518        {
   1519          fmtn('Lambda', '\\di', ':0:0:{'),
   1520          children = {
   1521            {
   1522              'Comma:0:2:,',
   1523              children = {
   1524                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1525                {
   1526                  'Comma:0:4:,',
   1527                  children = {
   1528                    'PlainIdentifier(scope=0,ident=b):0:3:b',
   1529                    'PlainIdentifier(scope=0,ident=c):0:5:c',
   1530                  },
   1531                },
   1532              },
   1533            },
   1534            {
   1535              'Arrow:0:6:->',
   1536              children = {
   1537                'Register(name=a):0:8:@a',
   1538              },
   1539            },
   1540          },
   1541        },
   1542      },
   1543    }, {
   1544      hl('Lambda', '{'),
   1545      hl('IdentifierName', 'a'),
   1546      hl('Comma', ','),
   1547      hl('IdentifierName', 'b'),
   1548      hl('Comma', ','),
   1549      hl('IdentifierName', 'c'),
   1550      hl('Arrow', '->'),
   1551      hl('Register', '@a'),
   1552      hl('Lambda', '}'),
   1553    })
   1554    check_parsing('{a,b,c,d->@a}', {
   1555      --           0123456789012
   1556      ast = {
   1557        {
   1558          fmtn('Lambda', '\\di', ':0:0:{'),
   1559          children = {
   1560            {
   1561              'Comma:0:2:,',
   1562              children = {
   1563                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1564                {
   1565                  'Comma:0:4:,',
   1566                  children = {
   1567                    'PlainIdentifier(scope=0,ident=b):0:3:b',
   1568                    {
   1569                      'Comma:0:6:,',
   1570                      children = {
   1571                        'PlainIdentifier(scope=0,ident=c):0:5:c',
   1572                        'PlainIdentifier(scope=0,ident=d):0:7:d',
   1573                      },
   1574                    },
   1575                  },
   1576                },
   1577              },
   1578            },
   1579            {
   1580              'Arrow:0:8:->',
   1581              children = {
   1582                'Register(name=a):0:10:@a',
   1583              },
   1584            },
   1585          },
   1586        },
   1587      },
   1588    }, {
   1589      hl('Lambda', '{'),
   1590      hl('IdentifierName', 'a'),
   1591      hl('Comma', ','),
   1592      hl('IdentifierName', 'b'),
   1593      hl('Comma', ','),
   1594      hl('IdentifierName', 'c'),
   1595      hl('Comma', ','),
   1596      hl('IdentifierName', 'd'),
   1597      hl('Arrow', '->'),
   1598      hl('Register', '@a'),
   1599      hl('Lambda', '}'),
   1600    })
   1601    check_parsing('{a,b,c,d,->@a}', {
   1602      --           01234567890123
   1603      ast = {
   1604        {
   1605          fmtn('Lambda', '\\di', ':0:0:{'),
   1606          children = {
   1607            {
   1608              'Comma:0:2:,',
   1609              children = {
   1610                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1611                {
   1612                  'Comma:0:4:,',
   1613                  children = {
   1614                    'PlainIdentifier(scope=0,ident=b):0:3:b',
   1615                    {
   1616                      'Comma:0:6:,',
   1617                      children = {
   1618                        'PlainIdentifier(scope=0,ident=c):0:5:c',
   1619                        {
   1620                          'Comma:0:8:,',
   1621                          children = {
   1622                            'PlainIdentifier(scope=0,ident=d):0:7:d',
   1623                          },
   1624                        },
   1625                      },
   1626                    },
   1627                  },
   1628                },
   1629              },
   1630            },
   1631            {
   1632              'Arrow:0:9:->',
   1633              children = {
   1634                'Register(name=a):0:11:@a',
   1635              },
   1636            },
   1637          },
   1638        },
   1639      },
   1640    }, {
   1641      hl('Lambda', '{'),
   1642      hl('IdentifierName', 'a'),
   1643      hl('Comma', ','),
   1644      hl('IdentifierName', 'b'),
   1645      hl('Comma', ','),
   1646      hl('IdentifierName', 'c'),
   1647      hl('Comma', ','),
   1648      hl('IdentifierName', 'd'),
   1649      hl('Comma', ','),
   1650      hl('Arrow', '->'),
   1651      hl('Register', '@a'),
   1652      hl('Lambda', '}'),
   1653    })
   1654    check_parsing('{a,b->{c,d->{e,f->@a}}}', {
   1655      --           01234567890123456789012
   1656      --           0         1         2
   1657      ast = {
   1658        {
   1659          fmtn('Lambda', '\\di', ':0:0:{'),
   1660          children = {
   1661            {
   1662              'Comma:0:2:,',
   1663              children = {
   1664                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1665                'PlainIdentifier(scope=0,ident=b):0:3:b',
   1666              },
   1667            },
   1668            {
   1669              'Arrow:0:4:->',
   1670              children = {
   1671                {
   1672                  fmtn('Lambda', '\\di', ':0:6:{'),
   1673                  children = {
   1674                    {
   1675                      'Comma:0:8:,',
   1676                      children = {
   1677                        'PlainIdentifier(scope=0,ident=c):0:7:c',
   1678                        'PlainIdentifier(scope=0,ident=d):0:9:d',
   1679                      },
   1680                    },
   1681                    {
   1682                      'Arrow:0:10:->',
   1683                      children = {
   1684                        {
   1685                          fmtn('Lambda', '\\di', ':0:12:{'),
   1686                          children = {
   1687                            {
   1688                              'Comma:0:14:,',
   1689                              children = {
   1690                                'PlainIdentifier(scope=0,ident=e):0:13:e',
   1691                                'PlainIdentifier(scope=0,ident=f):0:15:f',
   1692                              },
   1693                            },
   1694                            {
   1695                              'Arrow:0:16:->',
   1696                              children = {
   1697                                'Register(name=a):0:18:@a',
   1698                              },
   1699                            },
   1700                          },
   1701                        },
   1702                      },
   1703                    },
   1704                  },
   1705                },
   1706              },
   1707            },
   1708          },
   1709        },
   1710      },
   1711    }, {
   1712      hl('Lambda', '{'),
   1713      hl('IdentifierName', 'a'),
   1714      hl('Comma', ','),
   1715      hl('IdentifierName', 'b'),
   1716      hl('Arrow', '->'),
   1717      hl('Lambda', '{'),
   1718      hl('IdentifierName', 'c'),
   1719      hl('Comma', ','),
   1720      hl('IdentifierName', 'd'),
   1721      hl('Arrow', '->'),
   1722      hl('Lambda', '{'),
   1723      hl('IdentifierName', 'e'),
   1724      hl('Comma', ','),
   1725      hl('IdentifierName', 'f'),
   1726      hl('Arrow', '->'),
   1727      hl('Register', '@a'),
   1728      hl('Lambda', '}'),
   1729      hl('Lambda', '}'),
   1730      hl('Lambda', '}'),
   1731    })
   1732    check_parsing('{a,b->c,d}', {
   1733      --           0123456789
   1734      ast = {
   1735        {
   1736          fmtn('Lambda', '\\di', ':0:0:{'),
   1737          children = {
   1738            {
   1739              'Comma:0:2:,',
   1740              children = {
   1741                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1742                'PlainIdentifier(scope=0,ident=b):0:3:b',
   1743              },
   1744            },
   1745            {
   1746              'Arrow:0:4:->',
   1747              children = {
   1748                {
   1749                  'Comma:0:7:,',
   1750                  children = {
   1751                    'PlainIdentifier(scope=0,ident=c):0:6:c',
   1752                    'PlainIdentifier(scope=0,ident=d):0:8:d',
   1753                  },
   1754                },
   1755              },
   1756            },
   1757          },
   1758        },
   1759      },
   1760      err = {
   1761        arg = ',d}',
   1762        msg = 'E15: Comma outside of call, lambda or literal: %.*s',
   1763      },
   1764    }, {
   1765      hl('Lambda', '{'),
   1766      hl('IdentifierName', 'a'),
   1767      hl('Comma', ','),
   1768      hl('IdentifierName', 'b'),
   1769      hl('Arrow', '->'),
   1770      hl('IdentifierName', 'c'),
   1771      hl('InvalidComma', ','),
   1772      hl('IdentifierName', 'd'),
   1773      hl('Lambda', '}'),
   1774    })
   1775    check_parsing('a,b,c,d', {
   1776      --           0123456789
   1777      ast = {
   1778        {
   1779          'Comma:0:1:,',
   1780          children = {
   1781            'PlainIdentifier(scope=0,ident=a):0:0:a',
   1782            {
   1783              'Comma:0:3:,',
   1784              children = {
   1785                'PlainIdentifier(scope=0,ident=b):0:2:b',
   1786                {
   1787                  'Comma:0:5:,',
   1788                  children = {
   1789                    'PlainIdentifier(scope=0,ident=c):0:4:c',
   1790                    'PlainIdentifier(scope=0,ident=d):0:6:d',
   1791                  },
   1792                },
   1793              },
   1794            },
   1795          },
   1796        },
   1797      },
   1798      err = {
   1799        arg = ',b,c,d',
   1800        msg = 'E15: Comma outside of call, lambda or literal: %.*s',
   1801      },
   1802    }, {
   1803      hl('IdentifierName', 'a'),
   1804      hl('InvalidComma', ','),
   1805      hl('IdentifierName', 'b'),
   1806      hl('InvalidComma', ','),
   1807      hl('IdentifierName', 'c'),
   1808      hl('InvalidComma', ','),
   1809      hl('IdentifierName', 'd'),
   1810    })
   1811    check_parsing('a,b,c,d,', {
   1812      --           0123456789
   1813      ast = {
   1814        {
   1815          'Comma:0:1:,',
   1816          children = {
   1817            'PlainIdentifier(scope=0,ident=a):0:0:a',
   1818            {
   1819              'Comma:0:3:,',
   1820              children = {
   1821                'PlainIdentifier(scope=0,ident=b):0:2:b',
   1822                {
   1823                  'Comma:0:5:,',
   1824                  children = {
   1825                    'PlainIdentifier(scope=0,ident=c):0:4:c',
   1826                    {
   1827                      'Comma:0:7:,',
   1828                      children = {
   1829                        'PlainIdentifier(scope=0,ident=d):0:6:d',
   1830                      },
   1831                    },
   1832                  },
   1833                },
   1834              },
   1835            },
   1836          },
   1837        },
   1838      },
   1839      err = {
   1840        arg = ',b,c,d,',
   1841        msg = 'E15: Comma outside of call, lambda or literal: %.*s',
   1842      },
   1843    }, {
   1844      hl('IdentifierName', 'a'),
   1845      hl('InvalidComma', ','),
   1846      hl('IdentifierName', 'b'),
   1847      hl('InvalidComma', ','),
   1848      hl('IdentifierName', 'c'),
   1849      hl('InvalidComma', ','),
   1850      hl('IdentifierName', 'd'),
   1851      hl('InvalidComma', ','),
   1852    })
   1853    check_parsing(',', {
   1854      --           0123456789
   1855      ast = {
   1856        {
   1857          'Comma:0:0:,',
   1858          children = {
   1859            'Missing:0:0:',
   1860          },
   1861        },
   1862      },
   1863      err = {
   1864        arg = ',',
   1865        msg = 'E15: Expected value, got comma: %.*s',
   1866      },
   1867    }, {
   1868      hl('InvalidComma', ','),
   1869    })
   1870    check_parsing('{,a->@a}', {
   1871      --           0123456789
   1872      ast = {
   1873        {
   1874          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   1875          children = {
   1876            {
   1877              'Arrow:0:3:->',
   1878              children = {
   1879                {
   1880                  'Comma:0:1:,',
   1881                  children = {
   1882                    'Missing:0:1:',
   1883                    'PlainIdentifier(scope=0,ident=a):0:2:a',
   1884                  },
   1885                },
   1886                'Register(name=a):0:5:@a',
   1887              },
   1888            },
   1889          },
   1890        },
   1891      },
   1892      err = {
   1893        arg = ',a->@a}',
   1894        msg = 'E15: Expected value, got comma: %.*s',
   1895      },
   1896    }, {
   1897      hl('Curly', '{'),
   1898      hl('InvalidComma', ','),
   1899      hl('IdentifierName', 'a'),
   1900      hl('InvalidArrow', '->'),
   1901      hl('Register', '@a'),
   1902      hl('Curly', '}'),
   1903    })
   1904    check_parsing('}', {
   1905      --           0123456789
   1906      ast = {
   1907        fmtn('UnknownFigure', '---', ':0:0:'),
   1908      },
   1909      err = {
   1910        arg = '}',
   1911        msg = 'E15: Unexpected closing figure brace: %.*s',
   1912      },
   1913    }, {
   1914      hl('InvalidFigureBrace', '}'),
   1915    })
   1916    check_parsing('{->}', {
   1917      --           0123456789
   1918      ast = {
   1919        {
   1920          fmtn('Lambda', '\\di', ':0:0:{'),
   1921          children = {
   1922            'Arrow:0:1:->',
   1923          },
   1924        },
   1925      },
   1926      err = {
   1927        arg = '}',
   1928        msg = 'E15: Expected value, got closing figure brace: %.*s',
   1929      },
   1930    }, {
   1931      hl('Lambda', '{'),
   1932      hl('Arrow', '->'),
   1933      hl('InvalidLambda', '}'),
   1934    })
   1935    check_parsing('{a,b}', {
   1936      --           0123456789
   1937      ast = {
   1938        {
   1939          fmtn('Lambda', '-di', ':0:0:{'),
   1940          children = {
   1941            {
   1942              'Comma:0:2:,',
   1943              children = {
   1944                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1945                'PlainIdentifier(scope=0,ident=b):0:3:b',
   1946              },
   1947            },
   1948          },
   1949        },
   1950      },
   1951      err = {
   1952        arg = '}',
   1953        msg = 'E15: Expected lambda arguments list or arrow: %.*s',
   1954      },
   1955    }, {
   1956      hl('Lambda', '{'),
   1957      hl('IdentifierName', 'a'),
   1958      hl('Comma', ','),
   1959      hl('IdentifierName', 'b'),
   1960      hl('InvalidLambda', '}'),
   1961    })
   1962    check_parsing('{a,}', {
   1963      --           0123456789
   1964      ast = {
   1965        {
   1966          fmtn('Lambda', '-di', ':0:0:{'),
   1967          children = {
   1968            {
   1969              'Comma:0:2:,',
   1970              children = {
   1971                'PlainIdentifier(scope=0,ident=a):0:1:a',
   1972              },
   1973            },
   1974          },
   1975        },
   1976      },
   1977      err = {
   1978        arg = '}',
   1979        msg = 'E15: Expected lambda arguments list or arrow: %.*s',
   1980      },
   1981    }, {
   1982      hl('Lambda', '{'),
   1983      hl('IdentifierName', 'a'),
   1984      hl('Comma', ','),
   1985      hl('InvalidLambda', '}'),
   1986    })
   1987    check_parsing('{@a:@b}', {
   1988      --           0123456789
   1989      ast = {
   1990        {
   1991          fmtn('DictLiteral', '-di', ':0:0:{'),
   1992          children = {
   1993            {
   1994              'Colon:0:3::',
   1995              children = {
   1996                'Register(name=a):0:1:@a',
   1997                'Register(name=b):0:4:@b',
   1998              },
   1999            },
   2000          },
   2001        },
   2002      },
   2003    }, {
   2004      hl('Dict', '{'),
   2005      hl('Register', '@a'),
   2006      hl('Colon', ':'),
   2007      hl('Register', '@b'),
   2008      hl('Dict', '}'),
   2009    })
   2010    check_parsing('{@a:@b,@c:@d}', {
   2011      --           0123456789012
   2012      --           0         1
   2013      ast = {
   2014        {
   2015          fmtn('DictLiteral', '-di', ':0:0:{'),
   2016          children = {
   2017            {
   2018              'Comma:0:6:,',
   2019              children = {
   2020                {
   2021                  'Colon:0:3::',
   2022                  children = {
   2023                    'Register(name=a):0:1:@a',
   2024                    'Register(name=b):0:4:@b',
   2025                  },
   2026                },
   2027                {
   2028                  'Colon:0:9::',
   2029                  children = {
   2030                    'Register(name=c):0:7:@c',
   2031                    'Register(name=d):0:10:@d',
   2032                  },
   2033                },
   2034              },
   2035            },
   2036          },
   2037        },
   2038      },
   2039    }, {
   2040      hl('Dict', '{'),
   2041      hl('Register', '@a'),
   2042      hl('Colon', ':'),
   2043      hl('Register', '@b'),
   2044      hl('Comma', ','),
   2045      hl('Register', '@c'),
   2046      hl('Colon', ':'),
   2047      hl('Register', '@d'),
   2048      hl('Dict', '}'),
   2049    })
   2050    check_parsing('{@a:@b,@c:@d,@e:@f,}', {
   2051      --           01234567890123456789
   2052      --           0         1
   2053      ast = {
   2054        {
   2055          fmtn('DictLiteral', '-di', ':0:0:{'),
   2056          children = {
   2057            {
   2058              'Comma:0:6:,',
   2059              children = {
   2060                {
   2061                  'Colon:0:3::',
   2062                  children = {
   2063                    'Register(name=a):0:1:@a',
   2064                    'Register(name=b):0:4:@b',
   2065                  },
   2066                },
   2067                {
   2068                  'Comma:0:12:,',
   2069                  children = {
   2070                    {
   2071                      'Colon:0:9::',
   2072                      children = {
   2073                        'Register(name=c):0:7:@c',
   2074                        'Register(name=d):0:10:@d',
   2075                      },
   2076                    },
   2077                    {
   2078                      'Comma:0:18:,',
   2079                      children = {
   2080                        {
   2081                          'Colon:0:15::',
   2082                          children = {
   2083                            'Register(name=e):0:13:@e',
   2084                            'Register(name=f):0:16:@f',
   2085                          },
   2086                        },
   2087                      },
   2088                    },
   2089                  },
   2090                },
   2091              },
   2092            },
   2093          },
   2094        },
   2095      },
   2096    }, {
   2097      hl('Dict', '{'),
   2098      hl('Register', '@a'),
   2099      hl('Colon', ':'),
   2100      hl('Register', '@b'),
   2101      hl('Comma', ','),
   2102      hl('Register', '@c'),
   2103      hl('Colon', ':'),
   2104      hl('Register', '@d'),
   2105      hl('Comma', ','),
   2106      hl('Register', '@e'),
   2107      hl('Colon', ':'),
   2108      hl('Register', '@f'),
   2109      hl('Comma', ','),
   2110      hl('Dict', '}'),
   2111    })
   2112    check_parsing('{@a:@b,@c:@d,@e:@f,@g:}', {
   2113      --           01234567890123456789012
   2114      --           0         1         2
   2115      ast = {
   2116        {
   2117          fmtn('DictLiteral', '-di', ':0:0:{'),
   2118          children = {
   2119            {
   2120              'Comma:0:6:,',
   2121              children = {
   2122                {
   2123                  'Colon:0:3::',
   2124                  children = {
   2125                    'Register(name=a):0:1:@a',
   2126                    'Register(name=b):0:4:@b',
   2127                  },
   2128                },
   2129                {
   2130                  'Comma:0:12:,',
   2131                  children = {
   2132                    {
   2133                      'Colon:0:9::',
   2134                      children = {
   2135                        'Register(name=c):0:7:@c',
   2136                        'Register(name=d):0:10:@d',
   2137                      },
   2138                    },
   2139                    {
   2140                      'Comma:0:18:,',
   2141                      children = {
   2142                        {
   2143                          'Colon:0:15::',
   2144                          children = {
   2145                            'Register(name=e):0:13:@e',
   2146                            'Register(name=f):0:16:@f',
   2147                          },
   2148                        },
   2149                        {
   2150                          'Colon:0:21::',
   2151                          children = {
   2152                            'Register(name=g):0:19:@g',
   2153                          },
   2154                        },
   2155                      },
   2156                    },
   2157                  },
   2158                },
   2159              },
   2160            },
   2161          },
   2162        },
   2163      },
   2164      err = {
   2165        arg = '}',
   2166        msg = 'E15: Expected value, got closing figure brace: %.*s',
   2167      },
   2168    }, {
   2169      hl('Dict', '{'),
   2170      hl('Register', '@a'),
   2171      hl('Colon', ':'),
   2172      hl('Register', '@b'),
   2173      hl('Comma', ','),
   2174      hl('Register', '@c'),
   2175      hl('Colon', ':'),
   2176      hl('Register', '@d'),
   2177      hl('Comma', ','),
   2178      hl('Register', '@e'),
   2179      hl('Colon', ':'),
   2180      hl('Register', '@f'),
   2181      hl('Comma', ','),
   2182      hl('Register', '@g'),
   2183      hl('Colon', ':'),
   2184      hl('InvalidDict', '}'),
   2185    })
   2186    check_parsing('{@a:@b,}', {
   2187      --           01234567890123
   2188      --           0         1
   2189      ast = {
   2190        {
   2191          fmtn('DictLiteral', '-di', ':0:0:{'),
   2192          children = {
   2193            {
   2194              'Comma:0:6:,',
   2195              children = {
   2196                {
   2197                  'Colon:0:3::',
   2198                  children = {
   2199                    'Register(name=a):0:1:@a',
   2200                    'Register(name=b):0:4:@b',
   2201                  },
   2202                },
   2203              },
   2204            },
   2205          },
   2206        },
   2207      },
   2208    }, {
   2209      hl('Dict', '{'),
   2210      hl('Register', '@a'),
   2211      hl('Colon', ':'),
   2212      hl('Register', '@b'),
   2213      hl('Comma', ','),
   2214      hl('Dict', '}'),
   2215    })
   2216    check_parsing('{({f -> g})(@h)(@i)}', {
   2217      --           01234567890123456789
   2218      --           0         1
   2219      ast = {
   2220        {
   2221          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   2222          children = {
   2223            {
   2224              'Call:0:15:(',
   2225              children = {
   2226                {
   2227                  'Call:0:11:(',
   2228                  children = {
   2229                    {
   2230                      'Nested:0:1:(',
   2231                      children = {
   2232                        {
   2233                          fmtn('Lambda', '\\di', ':0:2:{'),
   2234                          children = {
   2235                            'PlainIdentifier(scope=0,ident=f):0:3:f',
   2236                            {
   2237                              'Arrow:0:4: ->',
   2238                              children = {
   2239                                'PlainIdentifier(scope=0,ident=g):0:7: g',
   2240                              },
   2241                            },
   2242                          },
   2243                        },
   2244                      },
   2245                    },
   2246                    'Register(name=h):0:12:@h',
   2247                  },
   2248                },
   2249                'Register(name=i):0:16:@i',
   2250              },
   2251            },
   2252          },
   2253        },
   2254      },
   2255    }, {
   2256      hl('Curly', '{'),
   2257      hl('NestingParenthesis', '('),
   2258      hl('Lambda', '{'),
   2259      hl('IdentifierName', 'f'),
   2260      hl('Arrow', '->', 1),
   2261      hl('IdentifierName', 'g', 1),
   2262      hl('Lambda', '}'),
   2263      hl('NestingParenthesis', ')'),
   2264      hl('CallingParenthesis', '('),
   2265      hl('Register', '@h'),
   2266      hl('CallingParenthesis', ')'),
   2267      hl('CallingParenthesis', '('),
   2268      hl('Register', '@i'),
   2269      hl('CallingParenthesis', ')'),
   2270      hl('Curly', '}'),
   2271    })
   2272    check_parsing('a:{b()}c', {
   2273      --           01234567
   2274      ast = {
   2275        {
   2276          'ComplexIdentifier:0:2:',
   2277          children = {
   2278            'PlainIdentifier(scope=a,ident=):0:0:a:',
   2279            {
   2280              'ComplexIdentifier:0:7:',
   2281              children = {
   2282                {
   2283                  fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   2284                  children = {
   2285                    {
   2286                      'Call:0:4:(',
   2287                      children = {
   2288                        'PlainIdentifier(scope=0,ident=b):0:3:b',
   2289                      },
   2290                    },
   2291                  },
   2292                },
   2293                'PlainIdentifier(scope=0,ident=c):0:7:c',
   2294              },
   2295            },
   2296          },
   2297        },
   2298      },
   2299    }, {
   2300      hl('IdentifierScope', 'a'),
   2301      hl('IdentifierScopeDelimiter', ':'),
   2302      hl('Curly', '{'),
   2303      hl('IdentifierName', 'b'),
   2304      hl('CallingParenthesis', '('),
   2305      hl('CallingParenthesis', ')'),
   2306      hl('Curly', '}'),
   2307      hl('IdentifierName', 'c'),
   2308    })
   2309    check_parsing('a:{{b, c -> @d + @e + ({f -> g})(@h)}(@i)}j', {
   2310      --           01234567890123456789012345678901234567890123456
   2311      --           0         1         2         3         4
   2312      ast = {
   2313        {
   2314          'ComplexIdentifier:0:2:',
   2315          children = {
   2316            'PlainIdentifier(scope=a,ident=):0:0:a:',
   2317            {
   2318              'ComplexIdentifier:0:42:',
   2319              children = {
   2320                {
   2321                  fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   2322                  children = {
   2323                    {
   2324                      'Call:0:37:(',
   2325                      children = {
   2326                        {
   2327                          fmtn('Lambda', '\\di', ':0:3:{'),
   2328                          children = {
   2329                            {
   2330                              'Comma:0:5:,',
   2331                              children = {
   2332                                'PlainIdentifier(scope=0,ident=b):0:4:b',
   2333                                'PlainIdentifier(scope=0,ident=c):0:6: c',
   2334                              },
   2335                            },
   2336                            {
   2337                              'Arrow:0:8: ->',
   2338                              children = {
   2339                                {
   2340                                  'BinaryPlus:0:19: +',
   2341                                  children = {
   2342                                    {
   2343                                      'BinaryPlus:0:14: +',
   2344                                      children = {
   2345                                        'Register(name=d):0:11: @d',
   2346                                        'Register(name=e):0:16: @e',
   2347                                      },
   2348                                    },
   2349                                    {
   2350                                      'Call:0:32:(',
   2351                                      children = {
   2352                                        {
   2353                                          'Nested:0:21: (',
   2354                                          children = {
   2355                                            {
   2356                                              fmtn('Lambda', '\\di', ':0:23:{'),
   2357                                              children = {
   2358                                                'PlainIdentifier(scope=0,ident=f):0:24:f',
   2359                                                {
   2360                                                  'Arrow:0:25: ->',
   2361                                                  children = {
   2362                                                    'PlainIdentifier(scope=0,ident=g):0:28: g',
   2363                                                  },
   2364                                                },
   2365                                              },
   2366                                            },
   2367                                          },
   2368                                        },
   2369                                        'Register(name=h):0:33:@h',
   2370                                      },
   2371                                    },
   2372                                  },
   2373                                },
   2374                              },
   2375                            },
   2376                          },
   2377                        },
   2378                        'Register(name=i):0:38:@i',
   2379                      },
   2380                    },
   2381                  },
   2382                },
   2383                'PlainIdentifier(scope=0,ident=j):0:42:j',
   2384              },
   2385            },
   2386          },
   2387        },
   2388      },
   2389    }, {
   2390      hl('IdentifierScope', 'a'),
   2391      hl('IdentifierScopeDelimiter', ':'),
   2392      hl('Curly', '{'),
   2393      hl('Lambda', '{'),
   2394      hl('IdentifierName', 'b'),
   2395      hl('Comma', ','),
   2396      hl('IdentifierName', 'c', 1),
   2397      hl('Arrow', '->', 1),
   2398      hl('Register', '@d', 1),
   2399      hl('BinaryPlus', '+', 1),
   2400      hl('Register', '@e', 1),
   2401      hl('BinaryPlus', '+', 1),
   2402      hl('NestingParenthesis', '(', 1),
   2403      hl('Lambda', '{'),
   2404      hl('IdentifierName', 'f'),
   2405      hl('Arrow', '->', 1),
   2406      hl('IdentifierName', 'g', 1),
   2407      hl('Lambda', '}'),
   2408      hl('NestingParenthesis', ')'),
   2409      hl('CallingParenthesis', '('),
   2410      hl('Register', '@h'),
   2411      hl('CallingParenthesis', ')'),
   2412      hl('Lambda', '}'),
   2413      hl('CallingParenthesis', '('),
   2414      hl('Register', '@i'),
   2415      hl('CallingParenthesis', ')'),
   2416      hl('Curly', '}'),
   2417      hl('IdentifierName', 'j'),
   2418    })
   2419    check_parsing('{@a + @b : @c + @d, @e + @f : @g + @i}', {
   2420      --           01234567890123456789012345678901234567
   2421      --           0         1         2         3
   2422      ast = {
   2423        {
   2424          fmtn('DictLiteral', '-di', ':0:0:{'),
   2425          children = {
   2426            {
   2427              'Comma:0:18:,',
   2428              children = {
   2429                {
   2430                  'Colon:0:8: :',
   2431                  children = {
   2432                    {
   2433                      'BinaryPlus:0:3: +',
   2434                      children = {
   2435                        'Register(name=a):0:1:@a',
   2436                        'Register(name=b):0:5: @b',
   2437                      },
   2438                    },
   2439                    {
   2440                      'BinaryPlus:0:13: +',
   2441                      children = {
   2442                        'Register(name=c):0:10: @c',
   2443                        'Register(name=d):0:15: @d',
   2444                      },
   2445                    },
   2446                  },
   2447                },
   2448                {
   2449                  'Colon:0:27: :',
   2450                  children = {
   2451                    {
   2452                      'BinaryPlus:0:22: +',
   2453                      children = {
   2454                        'Register(name=e):0:19: @e',
   2455                        'Register(name=f):0:24: @f',
   2456                      },
   2457                    },
   2458                    {
   2459                      'BinaryPlus:0:32: +',
   2460                      children = {
   2461                        'Register(name=g):0:29: @g',
   2462                        'Register(name=i):0:34: @i',
   2463                      },
   2464                    },
   2465                  },
   2466                },
   2467              },
   2468            },
   2469          },
   2470        },
   2471      },
   2472    }, {
   2473      hl('Dict', '{'),
   2474      hl('Register', '@a'),
   2475      hl('BinaryPlus', '+', 1),
   2476      hl('Register', '@b', 1),
   2477      hl('Colon', ':', 1),
   2478      hl('Register', '@c', 1),
   2479      hl('BinaryPlus', '+', 1),
   2480      hl('Register', '@d', 1),
   2481      hl('Comma', ','),
   2482      hl('Register', '@e', 1),
   2483      hl('BinaryPlus', '+', 1),
   2484      hl('Register', '@f', 1),
   2485      hl('Colon', ':', 1),
   2486      hl('Register', '@g', 1),
   2487      hl('BinaryPlus', '+', 1),
   2488      hl('Register', '@i', 1),
   2489      hl('Dict', '}'),
   2490    })
   2491    check_parsing('-> -> ->', {
   2492      --           01234567
   2493      ast = {
   2494        {
   2495          'Arrow:0:0:->',
   2496          children = {
   2497            'Missing:0:0:',
   2498            {
   2499              'Arrow:0:2: ->',
   2500              children = {
   2501                'Missing:0:2:',
   2502                {
   2503                  'Arrow:0:5: ->',
   2504                  children = {
   2505                    'Missing:0:5:',
   2506                  },
   2507                },
   2508              },
   2509            },
   2510          },
   2511        },
   2512      },
   2513      err = {
   2514        arg = '-> -> ->',
   2515        msg = 'E15: Unexpected arrow: %.*s',
   2516      },
   2517    }, {
   2518      hl('InvalidArrow', '->'),
   2519      hl('InvalidArrow', '->', 1),
   2520      hl('InvalidArrow', '->', 1),
   2521    })
   2522    check_parsing('a -> b -> c -> d', {
   2523      --           0123456789012345
   2524      --           0         1
   2525      ast = {
   2526        {
   2527          'Arrow:0:1: ->',
   2528          children = {
   2529            'PlainIdentifier(scope=0,ident=a):0:0:a',
   2530            {
   2531              'Arrow:0:6: ->',
   2532              children = {
   2533                'PlainIdentifier(scope=0,ident=b):0:4: b',
   2534                {
   2535                  'Arrow:0:11: ->',
   2536                  children = {
   2537                    'PlainIdentifier(scope=0,ident=c):0:9: c',
   2538                    'PlainIdentifier(scope=0,ident=d):0:14: d',
   2539                  },
   2540                },
   2541              },
   2542            },
   2543          },
   2544        },
   2545      },
   2546      err = {
   2547        arg = '-> b -> c -> d',
   2548        msg = 'E15: Arrow outside of lambda: %.*s',
   2549      },
   2550    }, {
   2551      hl('IdentifierName', 'a'),
   2552      hl('InvalidArrow', '->', 1),
   2553      hl('IdentifierName', 'b', 1),
   2554      hl('InvalidArrow', '->', 1),
   2555      hl('IdentifierName', 'c', 1),
   2556      hl('InvalidArrow', '->', 1),
   2557      hl('IdentifierName', 'd', 1),
   2558    })
   2559    check_parsing('{a -> b -> c}', {
   2560      --           0123456789012
   2561      --           0         1
   2562      ast = {
   2563        {
   2564          fmtn('Lambda', '\\di', ':0:0:{'),
   2565          children = {
   2566            'PlainIdentifier(scope=0,ident=a):0:1:a',
   2567            {
   2568              'Arrow:0:2: ->',
   2569              children = {
   2570                {
   2571                  'Arrow:0:7: ->',
   2572                  children = {
   2573                    'PlainIdentifier(scope=0,ident=b):0:5: b',
   2574                    'PlainIdentifier(scope=0,ident=c):0:10: c',
   2575                  },
   2576                },
   2577              },
   2578            },
   2579          },
   2580        },
   2581      },
   2582      err = {
   2583        arg = '-> c}',
   2584        msg = 'E15: Arrow outside of lambda: %.*s',
   2585      },
   2586    }, {
   2587      hl('Lambda', '{'),
   2588      hl('IdentifierName', 'a'),
   2589      hl('Arrow', '->', 1),
   2590      hl('IdentifierName', 'b', 1),
   2591      hl('InvalidArrow', '->', 1),
   2592      hl('IdentifierName', 'c', 1),
   2593      hl('Lambda', '}'),
   2594    })
   2595    check_parsing('{a: -> b}', {
   2596      --           012345678
   2597      ast = {
   2598        {
   2599          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   2600          children = {
   2601            {
   2602              'Arrow:0:3: ->',
   2603              children = {
   2604                'PlainIdentifier(scope=a,ident=):0:1:a:',
   2605                'PlainIdentifier(scope=0,ident=b):0:6: b',
   2606              },
   2607            },
   2608          },
   2609        },
   2610      },
   2611      err = {
   2612        arg = '-> b}',
   2613        msg = 'E15: Arrow outside of lambda: %.*s',
   2614      },
   2615    }, {
   2616      hl('Curly', '{'),
   2617      hl('IdentifierScope', 'a'),
   2618      hl('IdentifierScopeDelimiter', ':'),
   2619      hl('InvalidArrow', '->', 1),
   2620      hl('IdentifierName', 'b', 1),
   2621      hl('Curly', '}'),
   2622    })
   2623 
   2624    check_parsing('{a:b -> b}', {
   2625      --           0123456789
   2626      ast = {
   2627        {
   2628          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   2629          children = {
   2630            {
   2631              'Arrow:0:4: ->',
   2632              children = {
   2633                'PlainIdentifier(scope=a,ident=b):0:1:a:b',
   2634                'PlainIdentifier(scope=0,ident=b):0:7: b',
   2635              },
   2636            },
   2637          },
   2638        },
   2639      },
   2640      err = {
   2641        arg = '-> b}',
   2642        msg = 'E15: Arrow outside of lambda: %.*s',
   2643      },
   2644    }, {
   2645      hl('Curly', '{'),
   2646      hl('IdentifierScope', 'a'),
   2647      hl('IdentifierScopeDelimiter', ':'),
   2648      hl('IdentifierName', 'b'),
   2649      hl('InvalidArrow', '->', 1),
   2650      hl('IdentifierName', 'b', 1),
   2651      hl('Curly', '}'),
   2652    })
   2653 
   2654    check_parsing('{a#b -> b}', {
   2655      --           0123456789
   2656      ast = {
   2657        {
   2658          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   2659          children = {
   2660            {
   2661              'Arrow:0:4: ->',
   2662              children = {
   2663                'PlainIdentifier(scope=0,ident=a#b):0:1:a#b',
   2664                'PlainIdentifier(scope=0,ident=b):0:7: b',
   2665              },
   2666            },
   2667          },
   2668        },
   2669      },
   2670      err = {
   2671        arg = '-> b}',
   2672        msg = 'E15: Arrow outside of lambda: %.*s',
   2673      },
   2674    }, {
   2675      hl('Curly', '{'),
   2676      hl('IdentifierName', 'a#b'),
   2677      hl('InvalidArrow', '->', 1),
   2678      hl('IdentifierName', 'b', 1),
   2679      hl('Curly', '}'),
   2680    })
   2681    check_parsing('{a : b : c}', {
   2682      --           01234567890
   2683      --           0         1
   2684      ast = {
   2685        {
   2686          fmtn('DictLiteral', '-di', ':0:0:{'),
   2687          children = {
   2688            {
   2689              'Colon:0:2: :',
   2690              children = {
   2691                'PlainIdentifier(scope=0,ident=a):0:1:a',
   2692                {
   2693                  'Colon:0:6: :',
   2694                  children = {
   2695                    'PlainIdentifier(scope=0,ident=b):0:4: b',
   2696                    'PlainIdentifier(scope=0,ident=c):0:8: c',
   2697                  },
   2698                },
   2699              },
   2700            },
   2701          },
   2702        },
   2703      },
   2704      err = {
   2705        arg = ': c}',
   2706        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   2707      },
   2708    }, {
   2709      hl('Dict', '{'),
   2710      hl('IdentifierName', 'a'),
   2711      hl('Colon', ':', 1),
   2712      hl('IdentifierName', 'b', 1),
   2713      hl('InvalidColon', ':', 1),
   2714      hl('IdentifierName', 'c', 1),
   2715      hl('Dict', '}'),
   2716    })
   2717    check_parsing('{', {
   2718      --           0
   2719      ast = {
   2720        fmtn('UnknownFigure', '\\di', ':0:0:{'),
   2721      },
   2722      err = {
   2723        arg = '{',
   2724        msg = 'E15: Missing closing figure brace: %.*s',
   2725      },
   2726    }, {
   2727      hl('FigureBrace', '{'),
   2728    })
   2729    check_parsing('{a', {
   2730      --           01
   2731      ast = {
   2732        {
   2733          fmtn('UnknownFigure', '\\di', ':0:0:{'),
   2734          children = {
   2735            'PlainIdentifier(scope=0,ident=a):0:1:a',
   2736          },
   2737        },
   2738      },
   2739      err = {
   2740        arg = '{a',
   2741        msg = 'E15: Missing closing figure brace: %.*s',
   2742      },
   2743    }, {
   2744      hl('FigureBrace', '{'),
   2745      hl('IdentifierName', 'a'),
   2746    })
   2747    check_parsing('{a,b', {
   2748      --           0123
   2749      ast = {
   2750        {
   2751          fmtn('Lambda', '\\di', ':0:0:{'),
   2752          children = {
   2753            {
   2754              'Comma:0:2:,',
   2755              children = {
   2756                'PlainIdentifier(scope=0,ident=a):0:1:a',
   2757                'PlainIdentifier(scope=0,ident=b):0:3:b',
   2758              },
   2759            },
   2760          },
   2761        },
   2762      },
   2763      err = {
   2764        arg = '{a,b',
   2765        msg = 'E15: Missing closing figure brace for lambda: %.*s',
   2766      },
   2767    }, {
   2768      hl('Lambda', '{'),
   2769      hl('IdentifierName', 'a'),
   2770      hl('Comma', ','),
   2771      hl('IdentifierName', 'b'),
   2772    })
   2773    check_parsing('{a,b->', {
   2774      --           012345
   2775      ast = {
   2776        {
   2777          fmtn('Lambda', '\\di', ':0:0:{'),
   2778          children = {
   2779            {
   2780              'Comma:0:2:,',
   2781              children = {
   2782                'PlainIdentifier(scope=0,ident=a):0:1:a',
   2783                'PlainIdentifier(scope=0,ident=b):0:3:b',
   2784              },
   2785            },
   2786            'Arrow:0:4:->',
   2787          },
   2788        },
   2789      },
   2790      err = {
   2791        arg = '',
   2792        msg = 'E15: Expected value, got EOC: %.*s',
   2793      },
   2794    }, {
   2795      hl('Lambda', '{'),
   2796      hl('IdentifierName', 'a'),
   2797      hl('Comma', ','),
   2798      hl('IdentifierName', 'b'),
   2799      hl('Arrow', '->'),
   2800    })
   2801    check_parsing('{a,b->c', {
   2802      --           0123456
   2803      ast = {
   2804        {
   2805          fmtn('Lambda', '\\di', ':0:0:{'),
   2806          children = {
   2807            {
   2808              'Comma:0:2:,',
   2809              children = {
   2810                'PlainIdentifier(scope=0,ident=a):0:1:a',
   2811                'PlainIdentifier(scope=0,ident=b):0:3:b',
   2812              },
   2813            },
   2814            {
   2815              'Arrow:0:4:->',
   2816              children = {
   2817                'PlainIdentifier(scope=0,ident=c):0:6:c',
   2818              },
   2819            },
   2820          },
   2821        },
   2822      },
   2823      err = {
   2824        arg = '{a,b->c',
   2825        msg = 'E15: Missing closing figure brace for lambda: %.*s',
   2826      },
   2827    }, {
   2828      hl('Lambda', '{'),
   2829      hl('IdentifierName', 'a'),
   2830      hl('Comma', ','),
   2831      hl('IdentifierName', 'b'),
   2832      hl('Arrow', '->'),
   2833      hl('IdentifierName', 'c'),
   2834    })
   2835    check_parsing('{a : b', {
   2836      --           012345
   2837      ast = {
   2838        {
   2839          fmtn('DictLiteral', '-di', ':0:0:{'),
   2840          children = {
   2841            {
   2842              'Colon:0:2: :',
   2843              children = {
   2844                'PlainIdentifier(scope=0,ident=a):0:1:a',
   2845                'PlainIdentifier(scope=0,ident=b):0:4: b',
   2846              },
   2847            },
   2848          },
   2849        },
   2850      },
   2851      err = {
   2852        arg = '{a : b',
   2853        msg = "E723: Missing end of Dictionary '}': %.*s",
   2854      },
   2855    }, {
   2856      hl('Dict', '{'),
   2857      hl('IdentifierName', 'a'),
   2858      hl('Colon', ':', 1),
   2859      hl('IdentifierName', 'b', 1),
   2860    })
   2861    check_parsing('{a : b,', {
   2862      --           0123456
   2863      ast = {
   2864        {
   2865          fmtn('DictLiteral', '-di', ':0:0:{'),
   2866          children = {
   2867            {
   2868              'Comma:0:6:,',
   2869              children = {
   2870                {
   2871                  'Colon:0:2: :',
   2872                  children = {
   2873                    'PlainIdentifier(scope=0,ident=a):0:1:a',
   2874                    'PlainIdentifier(scope=0,ident=b):0:4: b',
   2875                  },
   2876                },
   2877              },
   2878            },
   2879          },
   2880        },
   2881      },
   2882      err = {
   2883        arg = '',
   2884        msg = 'E15: Expected value, got EOC: %.*s',
   2885      },
   2886    }, {
   2887      hl('Dict', '{'),
   2888      hl('IdentifierName', 'a'),
   2889      hl('Colon', ':', 1),
   2890      hl('IdentifierName', 'b', 1),
   2891      hl('Comma', ','),
   2892    })
   2893  end)
   2894  itp('works with ternary operator', function()
   2895    check_parsing('a ? b : c', {
   2896      --           012345678
   2897      ast = {
   2898        {
   2899          'Ternary:0:1: ?',
   2900          children = {
   2901            'PlainIdentifier(scope=0,ident=a):0:0:a',
   2902            {
   2903              'TernaryValue:0:5: :',
   2904              children = {
   2905                'PlainIdentifier(scope=0,ident=b):0:3: b',
   2906                'PlainIdentifier(scope=0,ident=c):0:7: c',
   2907              },
   2908            },
   2909          },
   2910        },
   2911      },
   2912    }, {
   2913      hl('IdentifierName', 'a'),
   2914      hl('Ternary', '?', 1),
   2915      hl('IdentifierName', 'b', 1),
   2916      hl('TernaryColon', ':', 1),
   2917      hl('IdentifierName', 'c', 1),
   2918    })
   2919    check_parsing('@a?@b?@c:@d:@e', {
   2920      --           01234567890123
   2921      --           0         1
   2922      ast = {
   2923        {
   2924          'Ternary:0:2:?',
   2925          children = {
   2926            'Register(name=a):0:0:@a',
   2927            {
   2928              'TernaryValue:0:11::',
   2929              children = {
   2930                {
   2931                  'Ternary:0:5:?',
   2932                  children = {
   2933                    'Register(name=b):0:3:@b',
   2934                    {
   2935                      'TernaryValue:0:8::',
   2936                      children = {
   2937                        'Register(name=c):0:6:@c',
   2938                        'Register(name=d):0:9:@d',
   2939                      },
   2940                    },
   2941                  },
   2942                },
   2943                'Register(name=e):0:12:@e',
   2944              },
   2945            },
   2946          },
   2947        },
   2948      },
   2949    }, {
   2950      hl('Register', '@a'),
   2951      hl('Ternary', '?'),
   2952      hl('Register', '@b'),
   2953      hl('Ternary', '?'),
   2954      hl('Register', '@c'),
   2955      hl('TernaryColon', ':'),
   2956      hl('Register', '@d'),
   2957      hl('TernaryColon', ':'),
   2958      hl('Register', '@e'),
   2959    })
   2960    check_parsing('@a?@b:@c?@d:@e', {
   2961      --           01234567890123
   2962      --           0         1
   2963      ast = {
   2964        {
   2965          'Ternary:0:2:?',
   2966          children = {
   2967            'Register(name=a):0:0:@a',
   2968            {
   2969              'TernaryValue:0:5::',
   2970              children = {
   2971                'Register(name=b):0:3:@b',
   2972                {
   2973                  'Ternary:0:8:?',
   2974                  children = {
   2975                    'Register(name=c):0:6:@c',
   2976                    {
   2977                      'TernaryValue:0:11::',
   2978                      children = {
   2979                        'Register(name=d):0:9:@d',
   2980                        'Register(name=e):0:12:@e',
   2981                      },
   2982                    },
   2983                  },
   2984                },
   2985              },
   2986            },
   2987          },
   2988        },
   2989      },
   2990    }, {
   2991      hl('Register', '@a'),
   2992      hl('Ternary', '?'),
   2993      hl('Register', '@b'),
   2994      hl('TernaryColon', ':'),
   2995      hl('Register', '@c'),
   2996      hl('Ternary', '?'),
   2997      hl('Register', '@d'),
   2998      hl('TernaryColon', ':'),
   2999      hl('Register', '@e'),
   3000    })
   3001    check_parsing('@a?@b?@c?@d:@e?@f:@g:@h?@i:@j:@k', {
   3002      --           01234567890123456789012345678901
   3003      --           0         1         2         3
   3004      ast = {
   3005        {
   3006          'Ternary:0:2:?',
   3007          children = {
   3008            'Register(name=a):0:0:@a',
   3009            {
   3010              'TernaryValue:0:29::',
   3011              children = {
   3012                {
   3013                  'Ternary:0:5:?',
   3014                  children = {
   3015                    'Register(name=b):0:3:@b',
   3016                    {
   3017                      'TernaryValue:0:20::',
   3018                      children = {
   3019                        {
   3020                          'Ternary:0:8:?',
   3021                          children = {
   3022                            'Register(name=c):0:6:@c',
   3023                            {
   3024                              'TernaryValue:0:11::',
   3025                              children = {
   3026                                'Register(name=d):0:9:@d',
   3027                                {
   3028                                  'Ternary:0:14:?',
   3029                                  children = {
   3030                                    'Register(name=e):0:12:@e',
   3031                                    {
   3032                                      'TernaryValue:0:17::',
   3033                                      children = {
   3034                                        'Register(name=f):0:15:@f',
   3035                                        'Register(name=g):0:18:@g',
   3036                                      },
   3037                                    },
   3038                                  },
   3039                                },
   3040                              },
   3041                            },
   3042                          },
   3043                        },
   3044                        {
   3045                          'Ternary:0:23:?',
   3046                          children = {
   3047                            'Register(name=h):0:21:@h',
   3048                            {
   3049                              'TernaryValue:0:26::',
   3050                              children = {
   3051                                'Register(name=i):0:24:@i',
   3052                                'Register(name=j):0:27:@j',
   3053                              },
   3054                            },
   3055                          },
   3056                        },
   3057                      },
   3058                    },
   3059                  },
   3060                },
   3061                'Register(name=k):0:30:@k',
   3062              },
   3063            },
   3064          },
   3065        },
   3066      },
   3067    }, {
   3068      hl('Register', '@a'),
   3069      hl('Ternary', '?'),
   3070      hl('Register', '@b'),
   3071      hl('Ternary', '?'),
   3072      hl('Register', '@c'),
   3073      hl('Ternary', '?'),
   3074      hl('Register', '@d'),
   3075      hl('TernaryColon', ':'),
   3076      hl('Register', '@e'),
   3077      hl('Ternary', '?'),
   3078      hl('Register', '@f'),
   3079      hl('TernaryColon', ':'),
   3080      hl('Register', '@g'),
   3081      hl('TernaryColon', ':'),
   3082      hl('Register', '@h'),
   3083      hl('Ternary', '?'),
   3084      hl('Register', '@i'),
   3085      hl('TernaryColon', ':'),
   3086      hl('Register', '@j'),
   3087      hl('TernaryColon', ':'),
   3088      hl('Register', '@k'),
   3089    })
   3090    check_parsing('?', {
   3091      --           0
   3092      ast = {
   3093        {
   3094          'Ternary:0:0:?',
   3095          children = {
   3096            'Missing:0:0:',
   3097            'TernaryValue:0:0:?',
   3098          },
   3099        },
   3100      },
   3101      err = {
   3102        arg = '?',
   3103        msg = 'E15: Expected value, got question mark: %.*s',
   3104      },
   3105    }, {
   3106      hl('InvalidTernary', '?'),
   3107    })
   3108 
   3109    check_parsing('?:', {
   3110      --           01
   3111      ast = {
   3112        {
   3113          'Ternary:0:0:?',
   3114          children = {
   3115            'Missing:0:0:',
   3116            {
   3117              'TernaryValue:0:1::',
   3118              children = {
   3119                'Missing:0:1:',
   3120              },
   3121            },
   3122          },
   3123        },
   3124      },
   3125      err = {
   3126        arg = '?:',
   3127        msg = 'E15: Expected value, got question mark: %.*s',
   3128      },
   3129    }, {
   3130      hl('InvalidTernary', '?'),
   3131      hl('InvalidTernaryColon', ':'),
   3132    })
   3133 
   3134    check_parsing('?::', {
   3135      --           012
   3136      ast = {
   3137        {
   3138          'Colon:0:2::',
   3139          children = {
   3140            {
   3141              'Ternary:0:0:?',
   3142              children = {
   3143                'Missing:0:0:',
   3144                {
   3145                  'TernaryValue:0:1::',
   3146                  children = {
   3147                    'Missing:0:1:',
   3148                    'Missing:0:2:',
   3149                  },
   3150                },
   3151              },
   3152            },
   3153          },
   3154        },
   3155      },
   3156      err = {
   3157        arg = '?::',
   3158        msg = 'E15: Expected value, got question mark: %.*s',
   3159      },
   3160    }, {
   3161      hl('InvalidTernary', '?'),
   3162      hl('InvalidTernaryColon', ':'),
   3163      hl('InvalidColon', ':'),
   3164    })
   3165 
   3166    check_parsing('a?b', {
   3167      --           012
   3168      ast = {
   3169        {
   3170          'Ternary:0:1:?',
   3171          children = {
   3172            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3173            {
   3174              'TernaryValue:0:1:?',
   3175              children = {
   3176                'PlainIdentifier(scope=0,ident=b):0:2:b',
   3177              },
   3178            },
   3179          },
   3180        },
   3181      },
   3182      err = {
   3183        arg = '?b',
   3184        msg = "E109: Missing ':' after '?': %.*s",
   3185      },
   3186    }, {
   3187      hl('IdentifierName', 'a'),
   3188      hl('Ternary', '?'),
   3189      hl('IdentifierName', 'b'),
   3190    })
   3191    check_parsing('a?b:', {
   3192      --           0123
   3193      ast = {
   3194        {
   3195          'Ternary:0:1:?',
   3196          children = {
   3197            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3198            {
   3199              'TernaryValue:0:1:?',
   3200              children = {
   3201                'PlainIdentifier(scope=b,ident=):0:2:b:',
   3202              },
   3203            },
   3204          },
   3205        },
   3206      },
   3207      err = {
   3208        arg = '?b:',
   3209        msg = "E109: Missing ':' after '?': %.*s",
   3210      },
   3211    }, {
   3212      hl('IdentifierName', 'a'),
   3213      hl('Ternary', '?'),
   3214      hl('IdentifierScope', 'b'),
   3215      hl('IdentifierScopeDelimiter', ':'),
   3216    })
   3217 
   3218    check_parsing('a?b::c', {
   3219      --           012345
   3220      ast = {
   3221        {
   3222          'Ternary:0:1:?',
   3223          children = {
   3224            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3225            {
   3226              'TernaryValue:0:4::',
   3227              children = {
   3228                'PlainIdentifier(scope=b,ident=):0:2:b:',
   3229                'PlainIdentifier(scope=0,ident=c):0:5:c',
   3230              },
   3231            },
   3232          },
   3233        },
   3234      },
   3235    }, {
   3236      hl('IdentifierName', 'a'),
   3237      hl('Ternary', '?'),
   3238      hl('IdentifierScope', 'b'),
   3239      hl('IdentifierScopeDelimiter', ':'),
   3240      hl('TernaryColon', ':'),
   3241      hl('IdentifierName', 'c'),
   3242    })
   3243 
   3244    check_parsing('a?b :', {
   3245      --           01234
   3246      ast = {
   3247        {
   3248          'Ternary:0:1:?',
   3249          children = {
   3250            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3251            {
   3252              'TernaryValue:0:3: :',
   3253              children = {
   3254                'PlainIdentifier(scope=0,ident=b):0:2:b',
   3255              },
   3256            },
   3257          },
   3258        },
   3259      },
   3260      err = {
   3261        arg = '',
   3262        msg = 'E15: Expected value, got EOC: %.*s',
   3263      },
   3264    }, {
   3265      hl('IdentifierName', 'a'),
   3266      hl('Ternary', '?'),
   3267      hl('IdentifierName', 'b'),
   3268      hl('TernaryColon', ':', 1),
   3269    })
   3270 
   3271    check_parsing('(@a?@b:@c)?@d:@e', {
   3272      --           0123456789012345
   3273      --           0         1
   3274      ast = {
   3275        {
   3276          'Ternary:0:10:?',
   3277          children = {
   3278            {
   3279              'Nested:0:0:(',
   3280              children = {
   3281                {
   3282                  'Ternary:0:3:?',
   3283                  children = {
   3284                    'Register(name=a):0:1:@a',
   3285                    {
   3286                      'TernaryValue:0:6::',
   3287                      children = {
   3288                        'Register(name=b):0:4:@b',
   3289                        'Register(name=c):0:7:@c',
   3290                      },
   3291                    },
   3292                  },
   3293                },
   3294              },
   3295            },
   3296            {
   3297              'TernaryValue:0:13::',
   3298              children = {
   3299                'Register(name=d):0:11:@d',
   3300                'Register(name=e):0:14:@e',
   3301              },
   3302            },
   3303          },
   3304        },
   3305      },
   3306    }, {
   3307      hl('NestingParenthesis', '('),
   3308      hl('Register', '@a'),
   3309      hl('Ternary', '?'),
   3310      hl('Register', '@b'),
   3311      hl('TernaryColon', ':'),
   3312      hl('Register', '@c'),
   3313      hl('NestingParenthesis', ')'),
   3314      hl('Ternary', '?'),
   3315      hl('Register', '@d'),
   3316      hl('TernaryColon', ':'),
   3317      hl('Register', '@e'),
   3318    })
   3319 
   3320    check_parsing('(@a?@b:@c)?(@d?@e:@f):(@g?@h:@i)', {
   3321      --           01234567890123456789012345678901
   3322      --           0         1         2         3
   3323      ast = {
   3324        {
   3325          'Ternary:0:10:?',
   3326          children = {
   3327            {
   3328              'Nested:0:0:(',
   3329              children = {
   3330                {
   3331                  'Ternary:0:3:?',
   3332                  children = {
   3333                    'Register(name=a):0:1:@a',
   3334                    {
   3335                      'TernaryValue:0:6::',
   3336                      children = {
   3337                        'Register(name=b):0:4:@b',
   3338                        'Register(name=c):0:7:@c',
   3339                      },
   3340                    },
   3341                  },
   3342                },
   3343              },
   3344            },
   3345            {
   3346              'TernaryValue:0:21::',
   3347              children = {
   3348                {
   3349                  'Nested:0:11:(',
   3350                  children = {
   3351                    {
   3352                      'Ternary:0:14:?',
   3353                      children = {
   3354                        'Register(name=d):0:12:@d',
   3355                        {
   3356                          'TernaryValue:0:17::',
   3357                          children = {
   3358                            'Register(name=e):0:15:@e',
   3359                            'Register(name=f):0:18:@f',
   3360                          },
   3361                        },
   3362                      },
   3363                    },
   3364                  },
   3365                },
   3366                {
   3367                  'Nested:0:22:(',
   3368                  children = {
   3369                    {
   3370                      'Ternary:0:25:?',
   3371                      children = {
   3372                        'Register(name=g):0:23:@g',
   3373                        {
   3374                          'TernaryValue:0:28::',
   3375                          children = {
   3376                            'Register(name=h):0:26:@h',
   3377                            'Register(name=i):0:29:@i',
   3378                          },
   3379                        },
   3380                      },
   3381                    },
   3382                  },
   3383                },
   3384              },
   3385            },
   3386          },
   3387        },
   3388      },
   3389    }, {
   3390      hl('NestingParenthesis', '('),
   3391      hl('Register', '@a'),
   3392      hl('Ternary', '?'),
   3393      hl('Register', '@b'),
   3394      hl('TernaryColon', ':'),
   3395      hl('Register', '@c'),
   3396      hl('NestingParenthesis', ')'),
   3397      hl('Ternary', '?'),
   3398      hl('NestingParenthesis', '('),
   3399      hl('Register', '@d'),
   3400      hl('Ternary', '?'),
   3401      hl('Register', '@e'),
   3402      hl('TernaryColon', ':'),
   3403      hl('Register', '@f'),
   3404      hl('NestingParenthesis', ')'),
   3405      hl('TernaryColon', ':'),
   3406      hl('NestingParenthesis', '('),
   3407      hl('Register', '@g'),
   3408      hl('Ternary', '?'),
   3409      hl('Register', '@h'),
   3410      hl('TernaryColon', ':'),
   3411      hl('Register', '@i'),
   3412      hl('NestingParenthesis', ')'),
   3413    })
   3414 
   3415    check_parsing('(@a?@b:@c)?@d?@e:@f:@g?@h:@i', {
   3416      --           0123456789012345678901234567
   3417      --           0         1         2
   3418      ast = {
   3419        {
   3420          'Ternary:0:10:?',
   3421          children = {
   3422            {
   3423              'Nested:0:0:(',
   3424              children = {
   3425                {
   3426                  'Ternary:0:3:?',
   3427                  children = {
   3428                    'Register(name=a):0:1:@a',
   3429                    {
   3430                      'TernaryValue:0:6::',
   3431                      children = {
   3432                        'Register(name=b):0:4:@b',
   3433                        'Register(name=c):0:7:@c',
   3434                      },
   3435                    },
   3436                  },
   3437                },
   3438              },
   3439            },
   3440            {
   3441              'TernaryValue:0:19::',
   3442              children = {
   3443                {
   3444                  'Ternary:0:13:?',
   3445                  children = {
   3446                    'Register(name=d):0:11:@d',
   3447                    {
   3448                      'TernaryValue:0:16::',
   3449                      children = {
   3450                        'Register(name=e):0:14:@e',
   3451                        'Register(name=f):0:17:@f',
   3452                      },
   3453                    },
   3454                  },
   3455                },
   3456                {
   3457                  'Ternary:0:22:?',
   3458                  children = {
   3459                    'Register(name=g):0:20:@g',
   3460                    {
   3461                      'TernaryValue:0:25::',
   3462                      children = {
   3463                        'Register(name=h):0:23:@h',
   3464                        'Register(name=i):0:26:@i',
   3465                      },
   3466                    },
   3467                  },
   3468                },
   3469              },
   3470            },
   3471          },
   3472        },
   3473      },
   3474    }, {
   3475      hl('NestingParenthesis', '('),
   3476      hl('Register', '@a'),
   3477      hl('Ternary', '?'),
   3478      hl('Register', '@b'),
   3479      hl('TernaryColon', ':'),
   3480      hl('Register', '@c'),
   3481      hl('NestingParenthesis', ')'),
   3482      hl('Ternary', '?'),
   3483      hl('Register', '@d'),
   3484      hl('Ternary', '?'),
   3485      hl('Register', '@e'),
   3486      hl('TernaryColon', ':'),
   3487      hl('Register', '@f'),
   3488      hl('TernaryColon', ':'),
   3489      hl('Register', '@g'),
   3490      hl('Ternary', '?'),
   3491      hl('Register', '@h'),
   3492      hl('TernaryColon', ':'),
   3493      hl('Register', '@i'),
   3494    })
   3495    check_parsing('a?b{cdef}g:h', {
   3496      --           012345678901
   3497      --           0         1
   3498      ast = {
   3499        {
   3500          'Ternary:0:1:?',
   3501          children = {
   3502            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3503            {
   3504              'TernaryValue:0:10::',
   3505              children = {
   3506                {
   3507                  'ComplexIdentifier:0:3:',
   3508                  children = {
   3509                    'PlainIdentifier(scope=0,ident=b):0:2:b',
   3510                    {
   3511                      'ComplexIdentifier:0:9:',
   3512                      children = {
   3513                        {
   3514                          fmtn('CurlyBracesIdentifier', '--i', ':0:3:{'),
   3515                          children = {
   3516                            'PlainIdentifier(scope=0,ident=cdef):0:4:cdef',
   3517                          },
   3518                        },
   3519                        'PlainIdentifier(scope=0,ident=g):0:9:g',
   3520                      },
   3521                    },
   3522                  },
   3523                },
   3524                'PlainIdentifier(scope=0,ident=h):0:11:h',
   3525              },
   3526            },
   3527          },
   3528        },
   3529      },
   3530    }, {
   3531      hl('IdentifierName', 'a'),
   3532      hl('Ternary', '?'),
   3533      hl('IdentifierName', 'b'),
   3534      hl('Curly', '{'),
   3535      hl('IdentifierName', 'cdef'),
   3536      hl('Curly', '}'),
   3537      hl('IdentifierName', 'g'),
   3538      hl('TernaryColon', ':'),
   3539      hl('IdentifierName', 'h'),
   3540    })
   3541    check_parsing('a ? b : c : d', {
   3542      --           0123456789012
   3543      --           0         1
   3544      ast = {
   3545        {
   3546          'Colon:0:9: :',
   3547          children = {
   3548            {
   3549              'Ternary:0:1: ?',
   3550              children = {
   3551                'PlainIdentifier(scope=0,ident=a):0:0:a',
   3552                {
   3553                  'TernaryValue:0:5: :',
   3554                  children = {
   3555                    'PlainIdentifier(scope=0,ident=b):0:3: b',
   3556                    'PlainIdentifier(scope=0,ident=c):0:7: c',
   3557                  },
   3558                },
   3559              },
   3560            },
   3561            'PlainIdentifier(scope=0,ident=d):0:11: d',
   3562          },
   3563        },
   3564      },
   3565      err = {
   3566        arg = ': d',
   3567        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   3568      },
   3569    }, {
   3570      hl('IdentifierName', 'a'),
   3571      hl('Ternary', '?', 1),
   3572      hl('IdentifierName', 'b', 1),
   3573      hl('TernaryColon', ':', 1),
   3574      hl('IdentifierName', 'c', 1),
   3575      hl('InvalidColon', ':', 1),
   3576      hl('IdentifierName', 'd', 1),
   3577    })
   3578  end)
   3579  itp('works with comparison operators', function()
   3580    check_parsing('a == b', {
   3581      --           012345
   3582      ast = {
   3583        {
   3584          'Comparison(type=Equal,inv=0,ccs=UseOption):0:1: ==',
   3585          children = {
   3586            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3587            'PlainIdentifier(scope=0,ident=b):0:4: b',
   3588          },
   3589        },
   3590      },
   3591    }, {
   3592      hl('IdentifierName', 'a'),
   3593      hl('Comparison', '==', 1),
   3594      hl('IdentifierName', 'b', 1),
   3595    })
   3596 
   3597    check_parsing('a ==? b', {
   3598      --           0123456
   3599      ast = {
   3600        {
   3601          'Comparison(type=Equal,inv=0,ccs=IgnoreCase):0:1: ==?',
   3602          children = {
   3603            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3604            'PlainIdentifier(scope=0,ident=b):0:5: b',
   3605          },
   3606        },
   3607      },
   3608    }, {
   3609      hl('IdentifierName', 'a'),
   3610      hl('Comparison', '==', 1),
   3611      hl('ComparisonModifier', '?'),
   3612      hl('IdentifierName', 'b', 1),
   3613    })
   3614 
   3615    check_parsing('a ==# b', {
   3616      --           0123456
   3617      ast = {
   3618        {
   3619          'Comparison(type=Equal,inv=0,ccs=MatchCase):0:1: ==#',
   3620          children = {
   3621            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3622            'PlainIdentifier(scope=0,ident=b):0:5: b',
   3623          },
   3624        },
   3625      },
   3626    }, {
   3627      hl('IdentifierName', 'a'),
   3628      hl('Comparison', '==', 1),
   3629      hl('ComparisonModifier', '#'),
   3630      hl('IdentifierName', 'b', 1),
   3631    })
   3632 
   3633    check_parsing('a !=# b', {
   3634      --           0123456
   3635      ast = {
   3636        {
   3637          'Comparison(type=Equal,inv=1,ccs=MatchCase):0:1: !=#',
   3638          children = {
   3639            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3640            'PlainIdentifier(scope=0,ident=b):0:5: b',
   3641          },
   3642        },
   3643      },
   3644    }, {
   3645      hl('IdentifierName', 'a'),
   3646      hl('Comparison', '!=', 1),
   3647      hl('ComparisonModifier', '#'),
   3648      hl('IdentifierName', 'b', 1),
   3649    })
   3650 
   3651    check_parsing('a <=# b', {
   3652      --           0123456
   3653      ast = {
   3654        {
   3655          'Comparison(type=Greater,inv=1,ccs=MatchCase):0:1: <=#',
   3656          children = {
   3657            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3658            'PlainIdentifier(scope=0,ident=b):0:5: b',
   3659          },
   3660        },
   3661      },
   3662    }, {
   3663      hl('IdentifierName', 'a'),
   3664      hl('Comparison', '<=', 1),
   3665      hl('ComparisonModifier', '#'),
   3666      hl('IdentifierName', 'b', 1),
   3667    })
   3668 
   3669    check_parsing('a >=# b', {
   3670      --           0123456
   3671      ast = {
   3672        {
   3673          'Comparison(type=GreaterOrEqual,inv=0,ccs=MatchCase):0:1: >=#',
   3674          children = {
   3675            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3676            'PlainIdentifier(scope=0,ident=b):0:5: b',
   3677          },
   3678        },
   3679      },
   3680    }, {
   3681      hl('IdentifierName', 'a'),
   3682      hl('Comparison', '>=', 1),
   3683      hl('ComparisonModifier', '#'),
   3684      hl('IdentifierName', 'b', 1),
   3685    })
   3686 
   3687    check_parsing('a ># b', {
   3688      --           012345
   3689      ast = {
   3690        {
   3691          'Comparison(type=Greater,inv=0,ccs=MatchCase):0:1: >#',
   3692          children = {
   3693            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3694            'PlainIdentifier(scope=0,ident=b):0:4: b',
   3695          },
   3696        },
   3697      },
   3698    }, {
   3699      hl('IdentifierName', 'a'),
   3700      hl('Comparison', '>', 1),
   3701      hl('ComparisonModifier', '#'),
   3702      hl('IdentifierName', 'b', 1),
   3703    })
   3704 
   3705    check_parsing('a <# b', {
   3706      --           012345
   3707      ast = {
   3708        {
   3709          'Comparison(type=GreaterOrEqual,inv=1,ccs=MatchCase):0:1: <#',
   3710          children = {
   3711            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3712            'PlainIdentifier(scope=0,ident=b):0:4: b',
   3713          },
   3714        },
   3715      },
   3716    }, {
   3717      hl('IdentifierName', 'a'),
   3718      hl('Comparison', '<', 1),
   3719      hl('ComparisonModifier', '#'),
   3720      hl('IdentifierName', 'b', 1),
   3721    })
   3722 
   3723    check_parsing('a is#b', {
   3724      --           012345
   3725      ast = {
   3726        {
   3727          'Comparison(type=Identical,inv=0,ccs=MatchCase):0:1: is#',
   3728          children = {
   3729            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3730            'PlainIdentifier(scope=0,ident=b):0:5:b',
   3731          },
   3732        },
   3733      },
   3734    }, {
   3735      hl('IdentifierName', 'a'),
   3736      hl('Comparison', 'is', 1),
   3737      hl('ComparisonModifier', '#'),
   3738      hl('IdentifierName', 'b'),
   3739    })
   3740 
   3741    check_parsing('a is?b', {
   3742      --           012345
   3743      ast = {
   3744        {
   3745          'Comparison(type=Identical,inv=0,ccs=IgnoreCase):0:1: is?',
   3746          children = {
   3747            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3748            'PlainIdentifier(scope=0,ident=b):0:5:b',
   3749          },
   3750        },
   3751      },
   3752    }, {
   3753      hl('IdentifierName', 'a'),
   3754      hl('Comparison', 'is', 1),
   3755      hl('ComparisonModifier', '?'),
   3756      hl('IdentifierName', 'b'),
   3757    })
   3758 
   3759    check_parsing('a isnot b', {
   3760      --           012345678
   3761      ast = {
   3762        {
   3763          'Comparison(type=Identical,inv=1,ccs=UseOption):0:1: isnot',
   3764          children = {
   3765            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3766            'PlainIdentifier(scope=0,ident=b):0:7: b',
   3767          },
   3768        },
   3769      },
   3770    }, {
   3771      hl('IdentifierName', 'a'),
   3772      hl('Comparison', 'isnot', 1),
   3773      hl('IdentifierName', 'b', 1),
   3774    })
   3775 
   3776    check_parsing('a < b < c', {
   3777      --           012345678
   3778      ast = {
   3779        {
   3780          'Comparison(type=GreaterOrEqual,inv=1,ccs=UseOption):0:1: <',
   3781          children = {
   3782            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3783            {
   3784              'Comparison(type=GreaterOrEqual,inv=1,ccs=UseOption):0:5: <',
   3785              children = {
   3786                'PlainIdentifier(scope=0,ident=b):0:3: b',
   3787                'PlainIdentifier(scope=0,ident=c):0:7: c',
   3788              },
   3789            },
   3790          },
   3791        },
   3792      },
   3793      err = {
   3794        arg = ' < c',
   3795        msg = 'E15: Operator is not associative: %.*s',
   3796      },
   3797    }, {
   3798      hl('IdentifierName', 'a'),
   3799      hl('Comparison', '<', 1),
   3800      hl('IdentifierName', 'b', 1),
   3801      hl('InvalidComparison', '<', 1),
   3802      hl('IdentifierName', 'c', 1),
   3803    })
   3804 
   3805    check_parsing('a < b <# c', {
   3806      --           012345678
   3807      ast = {
   3808        {
   3809          'Comparison(type=GreaterOrEqual,inv=1,ccs=UseOption):0:1: <',
   3810          children = {
   3811            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3812            {
   3813              'Comparison(type=GreaterOrEqual,inv=1,ccs=MatchCase):0:5: <#',
   3814              children = {
   3815                'PlainIdentifier(scope=0,ident=b):0:3: b',
   3816                'PlainIdentifier(scope=0,ident=c):0:8: c',
   3817              },
   3818            },
   3819          },
   3820        },
   3821      },
   3822      err = {
   3823        arg = ' <# c',
   3824        msg = 'E15: Operator is not associative: %.*s',
   3825      },
   3826    }, {
   3827      hl('IdentifierName', 'a'),
   3828      hl('Comparison', '<', 1),
   3829      hl('IdentifierName', 'b', 1),
   3830      hl('InvalidComparison', '<', 1),
   3831      hl('InvalidComparisonModifier', '#'),
   3832      hl('IdentifierName', 'c', 1),
   3833    })
   3834 
   3835    check_parsing('a += b', {
   3836      --           012345
   3837      ast = {
   3838        {
   3839          'Assignment(Add):0:1: +=',
   3840          children = {
   3841            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3842            'PlainIdentifier(scope=0,ident=b):0:4: b',
   3843          },
   3844        },
   3845      },
   3846      err = {
   3847        arg = '+= b',
   3848        msg = 'E15: Misplaced assignment: %.*s',
   3849      },
   3850    }, {
   3851      hl('IdentifierName', 'a'),
   3852      hl('InvalidAssignmentWithAddition', '+=', 1),
   3853      hl('IdentifierName', 'b', 1),
   3854    })
   3855    check_parsing('a + b == c + d', {
   3856      --           01234567890123
   3857      --           0         1
   3858      ast = {
   3859        {
   3860          'Comparison(type=Equal,inv=0,ccs=UseOption):0:5: ==',
   3861          children = {
   3862            {
   3863              'BinaryPlus:0:1: +',
   3864              children = {
   3865                'PlainIdentifier(scope=0,ident=a):0:0:a',
   3866                'PlainIdentifier(scope=0,ident=b):0:3: b',
   3867              },
   3868            },
   3869            {
   3870              'BinaryPlus:0:10: +',
   3871              children = {
   3872                'PlainIdentifier(scope=0,ident=c):0:8: c',
   3873                'PlainIdentifier(scope=0,ident=d):0:12: d',
   3874              },
   3875            },
   3876          },
   3877        },
   3878      },
   3879    }, {
   3880      hl('IdentifierName', 'a'),
   3881      hl('BinaryPlus', '+', 1),
   3882      hl('IdentifierName', 'b', 1),
   3883      hl('Comparison', '==', 1),
   3884      hl('IdentifierName', 'c', 1),
   3885      hl('BinaryPlus', '+', 1),
   3886      hl('IdentifierName', 'd', 1),
   3887    })
   3888    check_parsing('+ a == + b', {
   3889      --           0123456789
   3890      ast = {
   3891        {
   3892          'Comparison(type=Equal,inv=0,ccs=UseOption):0:3: ==',
   3893          children = {
   3894            {
   3895              'UnaryPlus:0:0:+',
   3896              children = {
   3897                'PlainIdentifier(scope=0,ident=a):0:1: a',
   3898              },
   3899            },
   3900            {
   3901              'UnaryPlus:0:6: +',
   3902              children = {
   3903                'PlainIdentifier(scope=0,ident=b):0:8: b',
   3904              },
   3905            },
   3906          },
   3907        },
   3908      },
   3909    }, {
   3910      hl('UnaryPlus', '+'),
   3911      hl('IdentifierName', 'a', 1),
   3912      hl('Comparison', '==', 1),
   3913      hl('UnaryPlus', '+', 1),
   3914      hl('IdentifierName', 'b', 1),
   3915    })
   3916  end)
   3917  itp('works with concat/subscript', function()
   3918    check_parsing('.', {
   3919      --           0
   3920      ast = {
   3921        {
   3922          'ConcatOrSubscript:0:0:.',
   3923          children = {
   3924            'Missing:0:0:',
   3925          },
   3926        },
   3927      },
   3928      err = {
   3929        arg = '.',
   3930        msg = 'E15: Unexpected dot: %.*s',
   3931      },
   3932    }, {
   3933      hl('InvalidConcatOrSubscript', '.'),
   3934    })
   3935 
   3936    check_parsing('a.', {
   3937      --           01
   3938      ast = {
   3939        {
   3940          'ConcatOrSubscript:0:1:.',
   3941          children = {
   3942            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3943          },
   3944        },
   3945      },
   3946      err = {
   3947        arg = '',
   3948        msg = 'E15: Expected value, got EOC: %.*s',
   3949      },
   3950    }, {
   3951      hl('IdentifierName', 'a'),
   3952      hl('ConcatOrSubscript', '.'),
   3953    })
   3954 
   3955    check_parsing('a.b', {
   3956      --           012
   3957      ast = {
   3958        {
   3959          'ConcatOrSubscript:0:1:.',
   3960          children = {
   3961            'PlainIdentifier(scope=0,ident=a):0:0:a',
   3962            'PlainKey(key=b):0:2:b',
   3963          },
   3964        },
   3965      },
   3966    }, {
   3967      hl('IdentifierName', 'a'),
   3968      hl('ConcatOrSubscript', '.'),
   3969      hl('IdentifierKey', 'b'),
   3970    })
   3971 
   3972    check_parsing('1.2', {
   3973      --           012
   3974      ast = {
   3975        'Float(val=1.200000e+00):0:0:1.2',
   3976      },
   3977    }, {
   3978      hl('Float', '1.2'),
   3979    })
   3980 
   3981    check_parsing('1.2 + 1.3e-5', {
   3982      --           012345678901
   3983      --           0         1
   3984      ast = {
   3985        {
   3986          'BinaryPlus:0:3: +',
   3987          children = {
   3988            'Float(val=1.200000e+00):0:0:1.2',
   3989            'Float(val=1.300000e-05):0:5: 1.3e-5',
   3990          },
   3991        },
   3992      },
   3993    }, {
   3994      hl('Float', '1.2'),
   3995      hl('BinaryPlus', '+', 1),
   3996      hl('Float', '1.3e-5', 1),
   3997    })
   3998 
   3999    check_parsing('a . 1.2 + 1.3e-5', {
   4000      --           0123456789012345
   4001      --           0         1
   4002      ast = {
   4003        {
   4004          'BinaryPlus:0:7: +',
   4005          children = {
   4006            {
   4007              'Concat:0:1: .',
   4008              children = {
   4009                'PlainIdentifier(scope=0,ident=a):0:0:a',
   4010                {
   4011                  'ConcatOrSubscript:0:5:.',
   4012                  children = {
   4013                    'Integer(val=1):0:3: 1',
   4014                    'PlainKey(key=2):0:6:2',
   4015                  },
   4016                },
   4017              },
   4018            },
   4019            'Float(val=1.300000e-05):0:9: 1.3e-5',
   4020          },
   4021        },
   4022      },
   4023    }, {
   4024      hl('IdentifierName', 'a'),
   4025      hl('Concat', '.', 1),
   4026      hl('Number', '1', 1),
   4027      hl('ConcatOrSubscript', '.'),
   4028      hl('IdentifierKey', '2'),
   4029      hl('BinaryPlus', '+', 1),
   4030      hl('Float', '1.3e-5', 1),
   4031    })
   4032 
   4033    check_parsing('1.3e-5 + 1.2 . a', {
   4034      --           0123456789012345
   4035      --           0         1
   4036      ast = {
   4037        {
   4038          'Concat:0:12: .',
   4039          children = {
   4040            {
   4041              'BinaryPlus:0:6: +',
   4042              children = {
   4043                'Float(val=1.300000e-05):0:0:1.3e-5',
   4044                'Float(val=1.200000e+00):0:8: 1.2',
   4045              },
   4046            },
   4047            'PlainIdentifier(scope=0,ident=a):0:14: a',
   4048          },
   4049        },
   4050      },
   4051    }, {
   4052      hl('Float', '1.3e-5'),
   4053      hl('BinaryPlus', '+', 1),
   4054      hl('Float', '1.2', 1),
   4055      hl('Concat', '.', 1),
   4056      hl('IdentifierName', 'a', 1),
   4057    })
   4058 
   4059    check_parsing('1.3e-5 + a . 1.2', {
   4060      --           0123456789012345
   4061      --           0         1
   4062      ast = {
   4063        {
   4064          'Concat:0:10: .',
   4065          children = {
   4066            {
   4067              'BinaryPlus:0:6: +',
   4068              children = {
   4069                'Float(val=1.300000e-05):0:0:1.3e-5',
   4070                'PlainIdentifier(scope=0,ident=a):0:8: a',
   4071              },
   4072            },
   4073            {
   4074              'ConcatOrSubscript:0:14:.',
   4075              children = {
   4076                'Integer(val=1):0:12: 1',
   4077                'PlainKey(key=2):0:15:2',
   4078              },
   4079            },
   4080          },
   4081        },
   4082      },
   4083    }, {
   4084      hl('Float', '1.3e-5'),
   4085      hl('BinaryPlus', '+', 1),
   4086      hl('IdentifierName', 'a', 1),
   4087      hl('Concat', '.', 1),
   4088      hl('Number', '1', 1),
   4089      hl('ConcatOrSubscript', '.'),
   4090      hl('IdentifierKey', '2'),
   4091    })
   4092 
   4093    check_parsing('1.2.3', {
   4094      --           01234
   4095      ast = {
   4096        {
   4097          'ConcatOrSubscript:0:3:.',
   4098          children = {
   4099            {
   4100              'ConcatOrSubscript:0:1:.',
   4101              children = {
   4102                'Integer(val=1):0:0:1',
   4103                'PlainKey(key=2):0:2:2',
   4104              },
   4105            },
   4106            'PlainKey(key=3):0:4:3',
   4107          },
   4108        },
   4109      },
   4110    }, {
   4111      hl('Number', '1'),
   4112      hl('ConcatOrSubscript', '.'),
   4113      hl('IdentifierKey', '2'),
   4114      hl('ConcatOrSubscript', '.'),
   4115      hl('IdentifierKey', '3'),
   4116    })
   4117 
   4118    check_parsing('a.1.2', {
   4119      --           01234
   4120      ast = {
   4121        {
   4122          'ConcatOrSubscript:0:3:.',
   4123          children = {
   4124            {
   4125              'ConcatOrSubscript:0:1:.',
   4126              children = {
   4127                'PlainIdentifier(scope=0,ident=a):0:0:a',
   4128                'PlainKey(key=1):0:2:1',
   4129              },
   4130            },
   4131            'PlainKey(key=2):0:4:2',
   4132          },
   4133        },
   4134      },
   4135    }, {
   4136      hl('IdentifierName', 'a'),
   4137      hl('ConcatOrSubscript', '.'),
   4138      hl('IdentifierKey', '1'),
   4139      hl('ConcatOrSubscript', '.'),
   4140      hl('IdentifierKey', '2'),
   4141    })
   4142 
   4143    check_parsing('a . 1.2', {
   4144      --           0123456
   4145      ast = {
   4146        {
   4147          'Concat:0:1: .',
   4148          children = {
   4149            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4150            {
   4151              'ConcatOrSubscript:0:5:.',
   4152              children = {
   4153                'Integer(val=1):0:3: 1',
   4154                'PlainKey(key=2):0:6:2',
   4155              },
   4156            },
   4157          },
   4158        },
   4159      },
   4160    }, {
   4161      hl('IdentifierName', 'a'),
   4162      hl('Concat', '.', 1),
   4163      hl('Number', '1', 1),
   4164      hl('ConcatOrSubscript', '.'),
   4165      hl('IdentifierKey', '2'),
   4166    })
   4167 
   4168    check_parsing('+a . +b', {
   4169      --           0123456
   4170      ast = {
   4171        {
   4172          'Concat:0:2: .',
   4173          children = {
   4174            {
   4175              'UnaryPlus:0:0:+',
   4176              children = {
   4177                'PlainIdentifier(scope=0,ident=a):0:1:a',
   4178              },
   4179            },
   4180            {
   4181              'UnaryPlus:0:4: +',
   4182              children = {
   4183                'PlainIdentifier(scope=0,ident=b):0:6:b',
   4184              },
   4185            },
   4186          },
   4187        },
   4188      },
   4189    }, {
   4190      hl('UnaryPlus', '+'),
   4191      hl('IdentifierName', 'a'),
   4192      hl('Concat', '.', 1),
   4193      hl('UnaryPlus', '+', 1),
   4194      hl('IdentifierName', 'b'),
   4195    })
   4196 
   4197    check_parsing('a. b', {
   4198      --           0123
   4199      ast = {
   4200        {
   4201          'Concat:0:1:.',
   4202          children = {
   4203            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4204            'PlainIdentifier(scope=0,ident=b):0:2: b',
   4205          },
   4206        },
   4207      },
   4208    }, {
   4209      hl('IdentifierName', 'a'),
   4210      hl('ConcatOrSubscript', '.'),
   4211      hl('IdentifierName', 'b', 1),
   4212    })
   4213 
   4214    check_parsing('a. 1', {
   4215      --           0123
   4216      ast = {
   4217        {
   4218          'Concat:0:1:.',
   4219          children = {
   4220            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4221            'Integer(val=1):0:2: 1',
   4222          },
   4223        },
   4224      },
   4225    }, {
   4226      hl('IdentifierName', 'a'),
   4227      hl('ConcatOrSubscript', '.'),
   4228      hl('Number', '1', 1),
   4229    })
   4230 
   4231    check_parsing('a[1][2][3[4', {
   4232      --           01234567890
   4233      --           0         1
   4234      ast = {
   4235        {
   4236          'Subscript:0:7:[',
   4237          children = {
   4238            {
   4239              'Subscript:0:4:[',
   4240              children = {
   4241                {
   4242                  'Subscript:0:1:[',
   4243                  children = {
   4244                    'PlainIdentifier(scope=0,ident=a):0:0:a',
   4245                    'Integer(val=1):0:2:1',
   4246                  },
   4247                },
   4248                'Integer(val=2):0:5:2',
   4249              },
   4250            },
   4251            {
   4252              'Subscript:0:9:[',
   4253              children = {
   4254                'Integer(val=3):0:8:3',
   4255                'Integer(val=4):0:10:4',
   4256              },
   4257            },
   4258          },
   4259        },
   4260      },
   4261    }, {
   4262      hl('IdentifierName', 'a'),
   4263      hl('SubscriptBracket', '['),
   4264      hl('Number', '1'),
   4265      hl('SubscriptBracket', ']'),
   4266      hl('SubscriptBracket', '['),
   4267      hl('Number', '2'),
   4268      hl('SubscriptBracket', ']'),
   4269      hl('SubscriptBracket', '['),
   4270      hl('Number', '3'),
   4271      hl('SubscriptBracket', '['),
   4272      hl('Number', '4'),
   4273    })
   4274  end)
   4275  itp('works with bracket subscripts', function()
   4276    check_parsing(':', {
   4277      --           0
   4278      ast = {
   4279        {
   4280          'Colon:0:0::',
   4281          children = {
   4282            'Missing:0:0:',
   4283          },
   4284        },
   4285      },
   4286      err = {
   4287        arg = ':',
   4288        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   4289      },
   4290    }, {
   4291      hl('InvalidColon', ':'),
   4292    })
   4293    check_parsing('a[]', {
   4294      --           012
   4295      ast = {
   4296        {
   4297          'Subscript:0:1:[',
   4298          children = {
   4299            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4300          },
   4301        },
   4302      },
   4303      err = {
   4304        arg = ']',
   4305        msg = 'E15: Expected value, got closing bracket: %.*s',
   4306      },
   4307    }, {
   4308      hl('IdentifierName', 'a'),
   4309      hl('SubscriptBracket', '['),
   4310      hl('InvalidSubscriptBracket', ']'),
   4311    })
   4312    check_parsing('a[b:]', {
   4313      --           01234
   4314      ast = {
   4315        {
   4316          'Subscript:0:1:[',
   4317          children = {
   4318            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4319            'PlainIdentifier(scope=b,ident=):0:2:b:',
   4320          },
   4321        },
   4322      },
   4323    }, {
   4324      hl('IdentifierName', 'a'),
   4325      hl('SubscriptBracket', '['),
   4326      hl('IdentifierScope', 'b'),
   4327      hl('IdentifierScopeDelimiter', ':'),
   4328      hl('SubscriptBracket', ']'),
   4329    })
   4330 
   4331    check_parsing('a[b:c]', {
   4332      --           012345
   4333      ast = {
   4334        {
   4335          'Subscript:0:1:[',
   4336          children = {
   4337            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4338            'PlainIdentifier(scope=b,ident=c):0:2:b:c',
   4339          },
   4340        },
   4341      },
   4342    }, {
   4343      hl('IdentifierName', 'a'),
   4344      hl('SubscriptBracket', '['),
   4345      hl('IdentifierScope', 'b'),
   4346      hl('IdentifierScopeDelimiter', ':'),
   4347      hl('IdentifierName', 'c'),
   4348      hl('SubscriptBracket', ']'),
   4349    })
   4350    check_parsing('a[b : c]', {
   4351      --           01234567
   4352      ast = {
   4353        {
   4354          'Subscript:0:1:[',
   4355          children = {
   4356            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4357            {
   4358              'Colon:0:3: :',
   4359              children = {
   4360                'PlainIdentifier(scope=0,ident=b):0:2:b',
   4361                'PlainIdentifier(scope=0,ident=c):0:5: c',
   4362              },
   4363            },
   4364          },
   4365        },
   4366      },
   4367    }, {
   4368      hl('IdentifierName', 'a'),
   4369      hl('SubscriptBracket', '['),
   4370      hl('IdentifierName', 'b'),
   4371      hl('SubscriptColon', ':', 1),
   4372      hl('IdentifierName', 'c', 1),
   4373      hl('SubscriptBracket', ']'),
   4374    })
   4375 
   4376    check_parsing('a[: b]', {
   4377      --           012345
   4378      ast = {
   4379        {
   4380          'Subscript:0:1:[',
   4381          children = {
   4382            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4383            {
   4384              'Colon:0:2::',
   4385              children = {
   4386                'Missing:0:2:',
   4387                'PlainIdentifier(scope=0,ident=b):0:3: b',
   4388              },
   4389            },
   4390          },
   4391        },
   4392      },
   4393    }, {
   4394      hl('IdentifierName', 'a'),
   4395      hl('SubscriptBracket', '['),
   4396      hl('SubscriptColon', ':'),
   4397      hl('IdentifierName', 'b', 1),
   4398      hl('SubscriptBracket', ']'),
   4399    })
   4400 
   4401    check_parsing('a[b :]', {
   4402      --           012345
   4403      ast = {
   4404        {
   4405          'Subscript:0:1:[',
   4406          children = {
   4407            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4408            {
   4409              'Colon:0:3: :',
   4410              children = {
   4411                'PlainIdentifier(scope=0,ident=b):0:2:b',
   4412              },
   4413            },
   4414          },
   4415        },
   4416      },
   4417    }, {
   4418      hl('IdentifierName', 'a'),
   4419      hl('SubscriptBracket', '['),
   4420      hl('IdentifierName', 'b'),
   4421      hl('SubscriptColon', ':', 1),
   4422      hl('SubscriptBracket', ']'),
   4423    })
   4424    check_parsing('a[b][c][d](e)(f)(g)', {
   4425      --           0123456789012345678
   4426      --           0         1
   4427      ast = {
   4428        {
   4429          'Call:0:16:(',
   4430          children = {
   4431            {
   4432              'Call:0:13:(',
   4433              children = {
   4434                {
   4435                  'Call:0:10:(',
   4436                  children = {
   4437                    {
   4438                      'Subscript:0:7:[',
   4439                      children = {
   4440                        {
   4441                          'Subscript:0:4:[',
   4442                          children = {
   4443                            {
   4444                              'Subscript:0:1:[',
   4445                              children = {
   4446                                'PlainIdentifier(scope=0,ident=a):0:0:a',
   4447                                'PlainIdentifier(scope=0,ident=b):0:2:b',
   4448                              },
   4449                            },
   4450                            'PlainIdentifier(scope=0,ident=c):0:5:c',
   4451                          },
   4452                        },
   4453                        'PlainIdentifier(scope=0,ident=d):0:8:d',
   4454                      },
   4455                    },
   4456                    'PlainIdentifier(scope=0,ident=e):0:11:e',
   4457                  },
   4458                },
   4459                'PlainIdentifier(scope=0,ident=f):0:14:f',
   4460              },
   4461            },
   4462            'PlainIdentifier(scope=0,ident=g):0:17:g',
   4463          },
   4464        },
   4465      },
   4466    }, {
   4467      hl('IdentifierName', 'a'),
   4468      hl('SubscriptBracket', '['),
   4469      hl('IdentifierName', 'b'),
   4470      hl('SubscriptBracket', ']'),
   4471      hl('SubscriptBracket', '['),
   4472      hl('IdentifierName', 'c'),
   4473      hl('SubscriptBracket', ']'),
   4474      hl('SubscriptBracket', '['),
   4475      hl('IdentifierName', 'd'),
   4476      hl('SubscriptBracket', ']'),
   4477      hl('CallingParenthesis', '('),
   4478      hl('IdentifierName', 'e'),
   4479      hl('CallingParenthesis', ')'),
   4480      hl('CallingParenthesis', '('),
   4481      hl('IdentifierName', 'f'),
   4482      hl('CallingParenthesis', ')'),
   4483      hl('CallingParenthesis', '('),
   4484      hl('IdentifierName', 'g'),
   4485      hl('CallingParenthesis', ')'),
   4486    })
   4487    check_parsing('{a}{b}{c}[d][e][f]', {
   4488      --           012345678901234567
   4489      --           0         1
   4490      ast = {
   4491        {
   4492          'Subscript:0:15:[',
   4493          children = {
   4494            {
   4495              'Subscript:0:12:[',
   4496              children = {
   4497                {
   4498                  'Subscript:0:9:[',
   4499                  children = {
   4500                    {
   4501                      'ComplexIdentifier:0:3:',
   4502                      children = {
   4503                        {
   4504                          fmtn('CurlyBracesIdentifier', '-di', ':0:0:{'),
   4505                          children = {
   4506                            'PlainIdentifier(scope=0,ident=a):0:1:a',
   4507                          },
   4508                        },
   4509                        {
   4510                          'ComplexIdentifier:0:6:',
   4511                          children = {
   4512                            {
   4513                              fmtn('CurlyBracesIdentifier', '--i', ':0:3:{'),
   4514                              children = {
   4515                                'PlainIdentifier(scope=0,ident=b):0:4:b',
   4516                              },
   4517                            },
   4518                            {
   4519                              fmtn('CurlyBracesIdentifier', '--i', ':0:6:{'),
   4520                              children = {
   4521                                'PlainIdentifier(scope=0,ident=c):0:7:c',
   4522                              },
   4523                            },
   4524                          },
   4525                        },
   4526                      },
   4527                    },
   4528                    'PlainIdentifier(scope=0,ident=d):0:10:d',
   4529                  },
   4530                },
   4531                'PlainIdentifier(scope=0,ident=e):0:13:e',
   4532              },
   4533            },
   4534            'PlainIdentifier(scope=0,ident=f):0:16:f',
   4535          },
   4536        },
   4537      },
   4538    }, {
   4539      hl('Curly', '{'),
   4540      hl('IdentifierName', 'a'),
   4541      hl('Curly', '}'),
   4542      hl('Curly', '{'),
   4543      hl('IdentifierName', 'b'),
   4544      hl('Curly', '}'),
   4545      hl('Curly', '{'),
   4546      hl('IdentifierName', 'c'),
   4547      hl('Curly', '}'),
   4548      hl('SubscriptBracket', '['),
   4549      hl('IdentifierName', 'd'),
   4550      hl('SubscriptBracket', ']'),
   4551      hl('SubscriptBracket', '['),
   4552      hl('IdentifierName', 'e'),
   4553      hl('SubscriptBracket', ']'),
   4554      hl('SubscriptBracket', '['),
   4555      hl('IdentifierName', 'f'),
   4556      hl('SubscriptBracket', ']'),
   4557    })
   4558  end)
   4559  itp('supports list literals', function()
   4560    check_parsing('[]', {
   4561      --           01
   4562      ast = {
   4563        'ListLiteral:0:0:[',
   4564      },
   4565    }, {
   4566      hl('List', '['),
   4567      hl('List', ']'),
   4568    })
   4569 
   4570    check_parsing('[a]', {
   4571      --           012
   4572      ast = {
   4573        {
   4574          'ListLiteral:0:0:[',
   4575          children = {
   4576            'PlainIdentifier(scope=0,ident=a):0:1:a',
   4577          },
   4578        },
   4579      },
   4580    }, {
   4581      hl('List', '['),
   4582      hl('IdentifierName', 'a'),
   4583      hl('List', ']'),
   4584    })
   4585 
   4586    check_parsing('[a, b]', {
   4587      --           012345
   4588      ast = {
   4589        {
   4590          'ListLiteral:0:0:[',
   4591          children = {
   4592            {
   4593              'Comma:0:2:,',
   4594              children = {
   4595                'PlainIdentifier(scope=0,ident=a):0:1:a',
   4596                'PlainIdentifier(scope=0,ident=b):0:3: b',
   4597              },
   4598            },
   4599          },
   4600        },
   4601      },
   4602    }, {
   4603      hl('List', '['),
   4604      hl('IdentifierName', 'a'),
   4605      hl('Comma', ','),
   4606      hl('IdentifierName', 'b', 1),
   4607      hl('List', ']'),
   4608    })
   4609 
   4610    check_parsing('[a, b, c]', {
   4611      --           012345678
   4612      ast = {
   4613        {
   4614          'ListLiteral:0:0:[',
   4615          children = {
   4616            {
   4617              'Comma:0:2:,',
   4618              children = {
   4619                'PlainIdentifier(scope=0,ident=a):0:1:a',
   4620                {
   4621                  'Comma:0:5:,',
   4622                  children = {
   4623                    'PlainIdentifier(scope=0,ident=b):0:3: b',
   4624                    'PlainIdentifier(scope=0,ident=c):0:6: c',
   4625                  },
   4626                },
   4627              },
   4628            },
   4629          },
   4630        },
   4631      },
   4632    }, {
   4633      hl('List', '['),
   4634      hl('IdentifierName', 'a'),
   4635      hl('Comma', ','),
   4636      hl('IdentifierName', 'b', 1),
   4637      hl('Comma', ','),
   4638      hl('IdentifierName', 'c', 1),
   4639      hl('List', ']'),
   4640    })
   4641 
   4642    check_parsing('[a, b, c, ]', {
   4643      --           01234567890
   4644      --           0         1
   4645      ast = {
   4646        {
   4647          'ListLiteral:0:0:[',
   4648          children = {
   4649            {
   4650              'Comma:0:2:,',
   4651              children = {
   4652                'PlainIdentifier(scope=0,ident=a):0:1:a',
   4653                {
   4654                  'Comma:0:5:,',
   4655                  children = {
   4656                    'PlainIdentifier(scope=0,ident=b):0:3: b',
   4657                    {
   4658                      'Comma:0:8:,',
   4659                      children = {
   4660                        'PlainIdentifier(scope=0,ident=c):0:6: c',
   4661                      },
   4662                    },
   4663                  },
   4664                },
   4665              },
   4666            },
   4667          },
   4668        },
   4669      },
   4670    }, {
   4671      hl('List', '['),
   4672      hl('IdentifierName', 'a'),
   4673      hl('Comma', ','),
   4674      hl('IdentifierName', 'b', 1),
   4675      hl('Comma', ','),
   4676      hl('IdentifierName', 'c', 1),
   4677      hl('Comma', ','),
   4678      hl('List', ']', 1),
   4679    })
   4680 
   4681    check_parsing('[a : b, c : d]', {
   4682      --           01234567890123
   4683      --           0         1
   4684      ast = {
   4685        {
   4686          'ListLiteral:0:0:[',
   4687          children = {
   4688            {
   4689              'Comma:0:6:,',
   4690              children = {
   4691                {
   4692                  'Colon:0:2: :',
   4693                  children = {
   4694                    'PlainIdentifier(scope=0,ident=a):0:1:a',
   4695                    'PlainIdentifier(scope=0,ident=b):0:4: b',
   4696                  },
   4697                },
   4698                {
   4699                  'Colon:0:9: :',
   4700                  children = {
   4701                    'PlainIdentifier(scope=0,ident=c):0:7: c',
   4702                    'PlainIdentifier(scope=0,ident=d):0:11: d',
   4703                  },
   4704                },
   4705              },
   4706            },
   4707          },
   4708        },
   4709      },
   4710      err = {
   4711        arg = ': b, c : d]',
   4712        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   4713      },
   4714    }, {
   4715      hl('List', '['),
   4716      hl('IdentifierName', 'a'),
   4717      hl('InvalidColon', ':', 1),
   4718      hl('IdentifierName', 'b', 1),
   4719      hl('Comma', ','),
   4720      hl('IdentifierName', 'c', 1),
   4721      hl('InvalidColon', ':', 1),
   4722      hl('IdentifierName', 'd', 1),
   4723      hl('List', ']'),
   4724    })
   4725 
   4726    check_parsing(']', {
   4727      --           0
   4728      ast = {
   4729        'ListLiteral:0:0:',
   4730      },
   4731      err = {
   4732        arg = ']',
   4733        msg = 'E15: Unexpected closing figure brace: %.*s',
   4734      },
   4735    }, {
   4736      hl('InvalidList', ']'),
   4737    })
   4738 
   4739    check_parsing('a]', {
   4740      --           01
   4741      ast = {
   4742        {
   4743          'ListLiteral:0:1:',
   4744          children = {
   4745            'PlainIdentifier(scope=0,ident=a):0:0:a',
   4746          },
   4747        },
   4748      },
   4749      err = {
   4750        arg = ']',
   4751        msg = 'E15: Unexpected closing figure brace: %.*s',
   4752      },
   4753    }, {
   4754      hl('IdentifierName', 'a'),
   4755      hl('InvalidList', ']'),
   4756    })
   4757 
   4758    check_parsing(']a', {
   4759      --           01
   4760      ast = {
   4761        {
   4762          'OpMissing:0:1:',
   4763          children = {
   4764            'ListLiteral:0:0:',
   4765            'PlainIdentifier(scope=0,ident=a):0:1:a',
   4766          },
   4767        },
   4768      },
   4769      err = {
   4770        arg = ']a',
   4771        msg = 'E15: Unexpected closing figure brace: %.*s',
   4772      },
   4773    }, {
   4774      hl('InvalidList', ']'),
   4775      hl('InvalidIdentifierName', 'a'),
   4776    }, {
   4777      [1] = {
   4778        ast = {
   4779          len = 1,
   4780          ast = {
   4781            'ListLiteral:0:0:',
   4782          },
   4783        },
   4784        hl_fs = {
   4785          [2] = REMOVE_THIS,
   4786        },
   4787      },
   4788    })
   4789 
   4790    check_parsing('[] []', {
   4791      --           01234
   4792      ast = {
   4793        {
   4794          'OpMissing:0:2:',
   4795          children = {
   4796            'ListLiteral:0:0:[',
   4797            'ListLiteral:0:2: [',
   4798          },
   4799        },
   4800      },
   4801      err = {
   4802        arg = '[]',
   4803        msg = 'E15: Missing operator: %.*s',
   4804      },
   4805    }, {
   4806      hl('List', '['),
   4807      hl('List', ']'),
   4808      hl('InvalidSpacing', ' '),
   4809      hl('List', '['),
   4810      hl('List', ']'),
   4811    }, {
   4812      [1] = {
   4813        ast = {
   4814          len = 3,
   4815          err = REMOVE_THIS,
   4816          ast = {
   4817            'ListLiteral:0:0:[',
   4818          },
   4819        },
   4820        hl_fs = {
   4821          [3] = REMOVE_THIS,
   4822          [4] = REMOVE_THIS,
   4823          [5] = REMOVE_THIS,
   4824        },
   4825      },
   4826    })
   4827 
   4828    check_parsing('[][]', {
   4829      --           0123
   4830      ast = {
   4831        {
   4832          'Subscript:0:2:[',
   4833          children = {
   4834            'ListLiteral:0:0:[',
   4835          },
   4836        },
   4837      },
   4838      err = {
   4839        arg = ']',
   4840        msg = 'E15: Expected value, got closing bracket: %.*s',
   4841      },
   4842    }, {
   4843      hl('List', '['),
   4844      hl('List', ']'),
   4845      hl('SubscriptBracket', '['),
   4846      hl('InvalidSubscriptBracket', ']'),
   4847    })
   4848 
   4849    check_parsing('[', {
   4850      --           0
   4851      ast = {
   4852        'ListLiteral:0:0:[',
   4853      },
   4854      err = {
   4855        arg = '',
   4856        msg = 'E15: Expected value, got EOC: %.*s',
   4857      },
   4858    }, {
   4859      hl('List', '['),
   4860    })
   4861 
   4862    check_parsing('[1', {
   4863      --           01
   4864      ast = {
   4865        {
   4866          'ListLiteral:0:0:[',
   4867          children = {
   4868            'Integer(val=1):0:1:1',
   4869          },
   4870        },
   4871      },
   4872      err = {
   4873        arg = '[1',
   4874        msg = "E697: Missing end of List ']': %.*s",
   4875      },
   4876    }, {
   4877      hl('List', '['),
   4878      hl('Number', '1'),
   4879    })
   4880  end)
   4881  itp('works with strings', function()
   4882    check_parsing("'abc'", {
   4883      --           01234
   4884      ast = {
   4885        fmtn('SingleQuotedString', 'val="abc"', ":0:0:'abc'"),
   4886      },
   4887    }, {
   4888      hl('SingleQuote', "'"),
   4889      hl('SingleQuotedBody', 'abc'),
   4890      hl('SingleQuote', "'"),
   4891    })
   4892    check_parsing('"abc"', {
   4893      --           01234
   4894      ast = {
   4895        fmtn('DoubleQuotedString', 'val="abc"', ':0:0:"abc"'),
   4896      },
   4897    }, {
   4898      hl('DoubleQuote', '"'),
   4899      hl('DoubleQuotedBody', 'abc'),
   4900      hl('DoubleQuote', '"'),
   4901    })
   4902    check_parsing("''", {
   4903      --           01
   4904      ast = {
   4905        fmtn('SingleQuotedString', 'val=NULL', ":0:0:''"),
   4906      },
   4907    }, {
   4908      hl('SingleQuote', "'"),
   4909      hl('SingleQuote', "'"),
   4910    })
   4911    check_parsing('""', {
   4912      --           01
   4913      ast = {
   4914        fmtn('DoubleQuotedString', 'val=NULL', ':0:0:""'),
   4915      },
   4916    }, {
   4917      hl('DoubleQuote', '"'),
   4918      hl('DoubleQuote', '"'),
   4919    })
   4920    check_parsing('"', {
   4921      --           0
   4922      ast = {
   4923        fmtn('DoubleQuotedString', 'val=NULL', ':0:0:"'),
   4924      },
   4925      err = {
   4926        arg = '"',
   4927        msg = 'E114: Missing double quote: %.*s',
   4928      },
   4929    }, {
   4930      hl('InvalidDoubleQuote', '"'),
   4931    })
   4932    check_parsing("'", {
   4933      --           0
   4934      ast = {
   4935        fmtn('SingleQuotedString', 'val=NULL', ":0:0:'"),
   4936      },
   4937      err = {
   4938        arg = "'",
   4939        msg = 'E115: Missing single quote: %.*s',
   4940      },
   4941    }, {
   4942      hl('InvalidSingleQuote', "'"),
   4943    })
   4944    check_parsing('"a', {
   4945      --           01
   4946      ast = {
   4947        fmtn('DoubleQuotedString', 'val="a"', ':0:0:"a'),
   4948      },
   4949      err = {
   4950        arg = '"a',
   4951        msg = 'E114: Missing double quote: %.*s',
   4952      },
   4953    }, {
   4954      hl('InvalidDoubleQuote', '"'),
   4955      hl('InvalidDoubleQuotedBody', 'a'),
   4956    })
   4957    check_parsing("'a", {
   4958      --           01
   4959      ast = {
   4960        fmtn('SingleQuotedString', 'val="a"', ":0:0:'a"),
   4961      },
   4962      err = {
   4963        arg = "'a",
   4964        msg = 'E115: Missing single quote: %.*s',
   4965      },
   4966    }, {
   4967      hl('InvalidSingleQuote', "'"),
   4968      hl('InvalidSingleQuotedBody', 'a'),
   4969    })
   4970    check_parsing("'abc''def'", {
   4971      --           0123456789
   4972      ast = {
   4973        fmtn('SingleQuotedString', 'val="abc\'def"', ":0:0:'abc''def'"),
   4974      },
   4975    }, {
   4976      hl('SingleQuote', "'"),
   4977      hl('SingleQuotedBody', 'abc'),
   4978      hl('SingleQuotedQuote', "''"),
   4979      hl('SingleQuotedBody', 'def'),
   4980      hl('SingleQuote', "'"),
   4981    })
   4982    check_parsing("'abc''", {
   4983      --           012345
   4984      ast = {
   4985        fmtn('SingleQuotedString', 'val="abc\'"', ":0:0:'abc''"),
   4986      },
   4987      err = {
   4988        arg = "'abc''",
   4989        msg = 'E115: Missing single quote: %.*s',
   4990      },
   4991    }, {
   4992      hl('InvalidSingleQuote', "'"),
   4993      hl('InvalidSingleQuotedBody', 'abc'),
   4994      hl('InvalidSingleQuotedQuote', "''"),
   4995    })
   4996    check_parsing("''''''''", {
   4997      --           01234567
   4998      ast = {
   4999        fmtn('SingleQuotedString', "val=\"'''\"", ":0:0:''''''''"),
   5000      },
   5001    }, {
   5002      hl('SingleQuote', "'"),
   5003      hl('SingleQuotedQuote', "''"),
   5004      hl('SingleQuotedQuote', "''"),
   5005      hl('SingleQuotedQuote', "''"),
   5006      hl('SingleQuote', "'"),
   5007    })
   5008    check_parsing("'''a''''bc'", {
   5009      --           01234567890
   5010      --           0         1
   5011      ast = {
   5012        fmtn('SingleQuotedString', "val=\"'a''bc\"", ":0:0:'''a''''bc'"),
   5013      },
   5014    }, {
   5015      hl('SingleQuote', "'"),
   5016      hl('SingleQuotedQuote', "''"),
   5017      hl('SingleQuotedBody', 'a'),
   5018      hl('SingleQuotedQuote', "''"),
   5019      hl('SingleQuotedQuote', "''"),
   5020      hl('SingleQuotedBody', 'bc'),
   5021      hl('SingleQuote', "'"),
   5022    })
   5023    check_parsing('"\\"\\"\\"\\""', {
   5024      --           0123456789
   5025      ast = {
   5026        fmtn('DoubleQuotedString', 'val="\\"\\"\\"\\""', ':0:0:"\\"\\"\\"\\""'),
   5027      },
   5028    }, {
   5029      hl('DoubleQuote', '"'),
   5030      hl('DoubleQuotedEscape', '\\"'),
   5031      hl('DoubleQuotedEscape', '\\"'),
   5032      hl('DoubleQuotedEscape', '\\"'),
   5033      hl('DoubleQuotedEscape', '\\"'),
   5034      hl('DoubleQuote', '"'),
   5035    })
   5036    check_parsing('"abc\\"def\\"ghi\\"jkl\\"mno"', {
   5037      --           0123456789012345678901234
   5038      --           0         1         2
   5039      ast = {
   5040        fmtn(
   5041          'DoubleQuotedString',
   5042          'val="abc\\"def\\"ghi\\"jkl\\"mno"',
   5043          ':0:0:"abc\\"def\\"ghi\\"jkl\\"mno"'
   5044        ),
   5045      },
   5046    }, {
   5047      hl('DoubleQuote', '"'),
   5048      hl('DoubleQuotedBody', 'abc'),
   5049      hl('DoubleQuotedEscape', '\\"'),
   5050      hl('DoubleQuotedBody', 'def'),
   5051      hl('DoubleQuotedEscape', '\\"'),
   5052      hl('DoubleQuotedBody', 'ghi'),
   5053      hl('DoubleQuotedEscape', '\\"'),
   5054      hl('DoubleQuotedBody', 'jkl'),
   5055      hl('DoubleQuotedEscape', '\\"'),
   5056      hl('DoubleQuotedBody', 'mno'),
   5057      hl('DoubleQuote', '"'),
   5058    })
   5059    check_parsing('"\\b\\e\\f\\r\\t\\\\"', {
   5060      --           0123456789012345
   5061      --           0         1
   5062      ast = {
   5063        [[DoubleQuotedString(val="\008\027\012\r\t\\"):0:0:"\b\e\f\r\t\\"]],
   5064      },
   5065    }, {
   5066      hl('DoubleQuote', '"'),
   5067      hl('DoubleQuotedEscape', '\\b'),
   5068      hl('DoubleQuotedEscape', '\\e'),
   5069      hl('DoubleQuotedEscape', '\\f'),
   5070      hl('DoubleQuotedEscape', '\\r'),
   5071      hl('DoubleQuotedEscape', '\\t'),
   5072      hl('DoubleQuotedEscape', '\\\\'),
   5073      hl('DoubleQuote', '"'),
   5074    })
   5075    check_parsing('"\\n\n"', {
   5076      --           01234
   5077      ast = {
   5078        fmtn('DoubleQuotedString', 'val="\\n\\n"', ':0:0:"\\n\n"'),
   5079      },
   5080    }, {
   5081      hl('DoubleQuote', '"'),
   5082      hl('DoubleQuotedEscape', '\\n'),
   5083      hl('DoubleQuotedBody', '\n'),
   5084      hl('DoubleQuote', '"'),
   5085    })
   5086    check_parsing('"\\x00"', {
   5087      --           012345
   5088      ast = {
   5089        fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\x00"'),
   5090      },
   5091    }, {
   5092      hl('DoubleQuote', '"'),
   5093      hl('DoubleQuotedEscape', '\\x00'),
   5094      hl('DoubleQuote', '"'),
   5095    })
   5096    check_parsing('"\\xFF"', {
   5097      --           012345
   5098      ast = {
   5099        fmtn('DoubleQuotedString', 'val="\255"', ':0:0:"\\xFF"'),
   5100      },
   5101    }, {
   5102      hl('DoubleQuote', '"'),
   5103      hl('DoubleQuotedEscape', '\\xFF'),
   5104      hl('DoubleQuote', '"'),
   5105    })
   5106    check_parsing('"\\xF"', {
   5107      --           012345
   5108      ast = {
   5109        fmtn('DoubleQuotedString', 'val="\\015"', ':0:0:"\\xF"'),
   5110      },
   5111    }, {
   5112      hl('DoubleQuote', '"'),
   5113      hl('DoubleQuotedEscape', '\\xF'),
   5114      hl('DoubleQuote', '"'),
   5115    })
   5116    check_parsing('"\\u00AB"', {
   5117      --           01234567
   5118      ast = {
   5119        fmtn('DoubleQuotedString', 'val="«"', ':0:0:"\\u00AB"'),
   5120      },
   5121    }, {
   5122      hl('DoubleQuote', '"'),
   5123      hl('DoubleQuotedEscape', '\\u00AB'),
   5124      hl('DoubleQuote', '"'),
   5125    })
   5126    check_parsing('"\\U000000AB"', {
   5127      --           01234567
   5128      ast = {
   5129        fmtn('DoubleQuotedString', 'val="«"', ':0:0:"\\U000000AB"'),
   5130      },
   5131    }, {
   5132      hl('DoubleQuote', '"'),
   5133      hl('DoubleQuotedEscape', '\\U000000AB'),
   5134      hl('DoubleQuote', '"'),
   5135    })
   5136    check_parsing('"\\x"', {
   5137      --           0123
   5138      ast = {
   5139        fmtn('DoubleQuotedString', 'val="x"', ':0:0:"\\x"'),
   5140      },
   5141    }, {
   5142      hl('DoubleQuote', '"'),
   5143      hl('DoubleQuotedUnknownEscape', '\\x'),
   5144      hl('DoubleQuote', '"'),
   5145    })
   5146 
   5147    check_parsing('"\\x', {
   5148      --           012
   5149      ast = {
   5150        fmtn('DoubleQuotedString', 'val="x"', ':0:0:"\\x'),
   5151      },
   5152      err = {
   5153        arg = '"\\x',
   5154        msg = 'E114: Missing double quote: %.*s',
   5155      },
   5156    }, {
   5157      hl('InvalidDoubleQuote', '"'),
   5158      hl('InvalidDoubleQuotedUnknownEscape', '\\x'),
   5159    })
   5160 
   5161    check_parsing('"\\xF', {
   5162      --           0123
   5163      ast = {
   5164        fmtn('DoubleQuotedString', 'val="\\015"', ':0:0:"\\xF'),
   5165      },
   5166      err = {
   5167        arg = '"\\xF',
   5168        msg = 'E114: Missing double quote: %.*s',
   5169      },
   5170    }, {
   5171      hl('InvalidDoubleQuote', '"'),
   5172      hl('InvalidDoubleQuotedEscape', '\\xF'),
   5173    })
   5174 
   5175    check_parsing('"\\u"', {
   5176      --           0123
   5177      ast = {
   5178        fmtn('DoubleQuotedString', 'val="u"', ':0:0:"\\u"'),
   5179      },
   5180    }, {
   5181      hl('DoubleQuote', '"'),
   5182      hl('DoubleQuotedUnknownEscape', '\\u'),
   5183      hl('DoubleQuote', '"'),
   5184    })
   5185 
   5186    check_parsing('"\\u', {
   5187      --           012
   5188      ast = {
   5189        fmtn('DoubleQuotedString', 'val="u"', ':0:0:"\\u'),
   5190      },
   5191      err = {
   5192        arg = '"\\u',
   5193        msg = 'E114: Missing double quote: %.*s',
   5194      },
   5195    }, {
   5196      hl('InvalidDoubleQuote', '"'),
   5197      hl('InvalidDoubleQuotedUnknownEscape', '\\u'),
   5198    })
   5199 
   5200    check_parsing('"\\U', {
   5201      --           012
   5202      ast = {
   5203        fmtn('DoubleQuotedString', 'val="U"', ':0:0:"\\U'),
   5204      },
   5205      err = {
   5206        arg = '"\\U',
   5207        msg = 'E114: Missing double quote: %.*s',
   5208      },
   5209    }, {
   5210      hl('InvalidDoubleQuote', '"'),
   5211      hl('InvalidDoubleQuotedUnknownEscape', '\\U'),
   5212    })
   5213 
   5214    check_parsing('"\\U"', {
   5215      --           0123
   5216      ast = {
   5217        fmtn('DoubleQuotedString', 'val="U"', ':0:0:"\\U"'),
   5218      },
   5219    }, {
   5220      hl('DoubleQuote', '"'),
   5221      hl('DoubleQuotedUnknownEscape', '\\U'),
   5222      hl('DoubleQuote', '"'),
   5223    })
   5224 
   5225    check_parsing('"\\xFX"', {
   5226      --           012345
   5227      ast = {
   5228        fmtn('DoubleQuotedString', 'val="\\015X"', ':0:0:"\\xFX"'),
   5229      },
   5230    }, {
   5231      hl('DoubleQuote', '"'),
   5232      hl('DoubleQuotedEscape', '\\xF'),
   5233      hl('DoubleQuotedBody', 'X'),
   5234      hl('DoubleQuote', '"'),
   5235    })
   5236 
   5237    check_parsing('"\\XFX"', {
   5238      --           012345
   5239      ast = {
   5240        fmtn('DoubleQuotedString', 'val="\\015X"', ':0:0:"\\XFX"'),
   5241      },
   5242    }, {
   5243      hl('DoubleQuote', '"'),
   5244      hl('DoubleQuotedEscape', '\\XF'),
   5245      hl('DoubleQuotedBody', 'X'),
   5246      hl('DoubleQuote', '"'),
   5247    })
   5248 
   5249    check_parsing('"\\xX"', {
   5250      --           01234
   5251      ast = {
   5252        fmtn('DoubleQuotedString', 'val="xX"', ':0:0:"\\xX"'),
   5253      },
   5254    }, {
   5255      hl('DoubleQuote', '"'),
   5256      hl('DoubleQuotedUnknownEscape', '\\x'),
   5257      hl('DoubleQuotedBody', 'X'),
   5258      hl('DoubleQuote', '"'),
   5259    })
   5260 
   5261    check_parsing('"\\XX"', {
   5262      --           01234
   5263      ast = {
   5264        fmtn('DoubleQuotedString', 'val="XX"', ':0:0:"\\XX"'),
   5265      },
   5266    }, {
   5267      hl('DoubleQuote', '"'),
   5268      hl('DoubleQuotedUnknownEscape', '\\X'),
   5269      hl('DoubleQuotedBody', 'X'),
   5270      hl('DoubleQuote', '"'),
   5271    })
   5272 
   5273    check_parsing('"\\uX"', {
   5274      --           01234
   5275      ast = {
   5276        fmtn('DoubleQuotedString', 'val="uX"', ':0:0:"\\uX"'),
   5277      },
   5278    }, {
   5279      hl('DoubleQuote', '"'),
   5280      hl('DoubleQuotedUnknownEscape', '\\u'),
   5281      hl('DoubleQuotedBody', 'X'),
   5282      hl('DoubleQuote', '"'),
   5283    })
   5284 
   5285    check_parsing('"\\UX"', {
   5286      --           01234
   5287      ast = {
   5288        fmtn('DoubleQuotedString', 'val="UX"', ':0:0:"\\UX"'),
   5289      },
   5290    }, {
   5291      hl('DoubleQuote', '"'),
   5292      hl('DoubleQuotedUnknownEscape', '\\U'),
   5293      hl('DoubleQuotedBody', 'X'),
   5294      hl('DoubleQuote', '"'),
   5295    })
   5296 
   5297    check_parsing('"\\x0X"', {
   5298      --           012345
   5299      ast = {
   5300        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\x0X"'),
   5301      },
   5302    }, {
   5303      hl('DoubleQuote', '"'),
   5304      hl('DoubleQuotedEscape', '\\x0'),
   5305      hl('DoubleQuotedBody', 'X'),
   5306      hl('DoubleQuote', '"'),
   5307    })
   5308 
   5309    check_parsing('"\\X0X"', {
   5310      --           012345
   5311      ast = {
   5312        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\X0X"'),
   5313      },
   5314    }, {
   5315      hl('DoubleQuote', '"'),
   5316      hl('DoubleQuotedEscape', '\\X0'),
   5317      hl('DoubleQuotedBody', 'X'),
   5318      hl('DoubleQuote', '"'),
   5319    })
   5320 
   5321    check_parsing('"\\u0X"', {
   5322      --           012345
   5323      ast = {
   5324        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u0X"'),
   5325      },
   5326    }, {
   5327      hl('DoubleQuote', '"'),
   5328      hl('DoubleQuotedEscape', '\\u0'),
   5329      hl('DoubleQuotedBody', 'X'),
   5330      hl('DoubleQuote', '"'),
   5331    })
   5332 
   5333    check_parsing('"\\U0X"', {
   5334      --           012345
   5335      ast = {
   5336        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U0X"'),
   5337      },
   5338    }, {
   5339      hl('DoubleQuote', '"'),
   5340      hl('DoubleQuotedEscape', '\\U0'),
   5341      hl('DoubleQuotedBody', 'X'),
   5342      hl('DoubleQuote', '"'),
   5343    })
   5344 
   5345    check_parsing('"\\x00X"', {
   5346      --           0123456
   5347      ast = {
   5348        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\x00X"'),
   5349      },
   5350    }, {
   5351      hl('DoubleQuote', '"'),
   5352      hl('DoubleQuotedEscape', '\\x00'),
   5353      hl('DoubleQuotedBody', 'X'),
   5354      hl('DoubleQuote', '"'),
   5355    })
   5356 
   5357    check_parsing('"\\X00X"', {
   5358      --           0123456
   5359      ast = {
   5360        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\X00X"'),
   5361      },
   5362    }, {
   5363      hl('DoubleQuote', '"'),
   5364      hl('DoubleQuotedEscape', '\\X00'),
   5365      hl('DoubleQuotedBody', 'X'),
   5366      hl('DoubleQuote', '"'),
   5367    })
   5368 
   5369    check_parsing('"\\u00X"', {
   5370      --           0123456
   5371      ast = {
   5372        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u00X"'),
   5373      },
   5374    }, {
   5375      hl('DoubleQuote', '"'),
   5376      hl('DoubleQuotedEscape', '\\u00'),
   5377      hl('DoubleQuotedBody', 'X'),
   5378      hl('DoubleQuote', '"'),
   5379    })
   5380 
   5381    check_parsing('"\\U00X"', {
   5382      --           0123456
   5383      ast = {
   5384        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U00X"'),
   5385      },
   5386    }, {
   5387      hl('DoubleQuote', '"'),
   5388      hl('DoubleQuotedEscape', '\\U00'),
   5389      hl('DoubleQuotedBody', 'X'),
   5390      hl('DoubleQuote', '"'),
   5391    })
   5392 
   5393    check_parsing('"\\u000X"', {
   5394      --           01234567
   5395      ast = {
   5396        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u000X"'),
   5397      },
   5398    }, {
   5399      hl('DoubleQuote', '"'),
   5400      hl('DoubleQuotedEscape', '\\u000'),
   5401      hl('DoubleQuotedBody', 'X'),
   5402      hl('DoubleQuote', '"'),
   5403    })
   5404 
   5405    check_parsing('"\\U000X"', {
   5406      --           01234567
   5407      ast = {
   5408        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U000X"'),
   5409      },
   5410    }, {
   5411      hl('DoubleQuote', '"'),
   5412      hl('DoubleQuotedEscape', '\\U000'),
   5413      hl('DoubleQuotedBody', 'X'),
   5414      hl('DoubleQuote', '"'),
   5415    })
   5416 
   5417    check_parsing('"\\u0000X"', {
   5418      --           012345678
   5419      ast = {
   5420        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u0000X"'),
   5421      },
   5422    }, {
   5423      hl('DoubleQuote', '"'),
   5424      hl('DoubleQuotedEscape', '\\u0000'),
   5425      hl('DoubleQuotedBody', 'X'),
   5426      hl('DoubleQuote', '"'),
   5427    })
   5428 
   5429    check_parsing('"\\U0000X"', {
   5430      --           012345678
   5431      ast = {
   5432        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U0000X"'),
   5433      },
   5434    }, {
   5435      hl('DoubleQuote', '"'),
   5436      hl('DoubleQuotedEscape', '\\U0000'),
   5437      hl('DoubleQuotedBody', 'X'),
   5438      hl('DoubleQuote', '"'),
   5439    })
   5440 
   5441    check_parsing('"\\U00000X"', {
   5442      --           0123456789
   5443      ast = {
   5444        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U00000X"'),
   5445      },
   5446    }, {
   5447      hl('DoubleQuote', '"'),
   5448      hl('DoubleQuotedEscape', '\\U00000'),
   5449      hl('DoubleQuotedBody', 'X'),
   5450      hl('DoubleQuote', '"'),
   5451    })
   5452 
   5453    check_parsing('"\\U000000X"', {
   5454      --           01234567890
   5455      --           0         1
   5456      ast = {
   5457        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U000000X"'),
   5458      },
   5459    }, {
   5460      hl('DoubleQuote', '"'),
   5461      hl('DoubleQuotedEscape', '\\U000000'),
   5462      hl('DoubleQuotedBody', 'X'),
   5463      hl('DoubleQuote', '"'),
   5464    })
   5465 
   5466    check_parsing('"\\U0000000X"', {
   5467      --           012345678901
   5468      --           0         1
   5469      ast = {
   5470        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U0000000X"'),
   5471      },
   5472    }, {
   5473      hl('DoubleQuote', '"'),
   5474      hl('DoubleQuotedEscape', '\\U0000000'),
   5475      hl('DoubleQuotedBody', 'X'),
   5476      hl('DoubleQuote', '"'),
   5477    })
   5478 
   5479    check_parsing('"\\U00000000X"', {
   5480      --           0123456789012
   5481      --           0         1
   5482      ast = {
   5483        fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U00000000X"'),
   5484      },
   5485    }, {
   5486      hl('DoubleQuote', '"'),
   5487      hl('DoubleQuotedEscape', '\\U00000000'),
   5488      hl('DoubleQuotedBody', 'X'),
   5489      hl('DoubleQuote', '"'),
   5490    })
   5491 
   5492    check_parsing('"\\x000X"', {
   5493      --           01234567
   5494      ast = {
   5495        fmtn('DoubleQuotedString', 'val="\\0000X"', ':0:0:"\\x000X"'),
   5496      },
   5497    }, {
   5498      hl('DoubleQuote', '"'),
   5499      hl('DoubleQuotedEscape', '\\x00'),
   5500      hl('DoubleQuotedBody', '0X'),
   5501      hl('DoubleQuote', '"'),
   5502    })
   5503 
   5504    check_parsing('"\\X000X"', {
   5505      --           01234567
   5506      ast = {
   5507        fmtn('DoubleQuotedString', 'val="\\0000X"', ':0:0:"\\X000X"'),
   5508      },
   5509    }, {
   5510      hl('DoubleQuote', '"'),
   5511      hl('DoubleQuotedEscape', '\\X00'),
   5512      hl('DoubleQuotedBody', '0X'),
   5513      hl('DoubleQuote', '"'),
   5514    })
   5515 
   5516    check_parsing('"\\u00000X"', {
   5517      --           0123456789
   5518      ast = {
   5519        fmtn('DoubleQuotedString', 'val="\\0000X"', ':0:0:"\\u00000X"'),
   5520      },
   5521    }, {
   5522      hl('DoubleQuote', '"'),
   5523      hl('DoubleQuotedEscape', '\\u0000'),
   5524      hl('DoubleQuotedBody', '0X'),
   5525      hl('DoubleQuote', '"'),
   5526    })
   5527 
   5528    check_parsing('"\\U000000000X"', {
   5529      --           01234567890123
   5530      --           0         1
   5531      ast = {
   5532        fmtn('DoubleQuotedString', 'val="\\0000X"', ':0:0:"\\U000000000X"'),
   5533      },
   5534    }, {
   5535      hl('DoubleQuote', '"'),
   5536      hl('DoubleQuotedEscape', '\\U00000000'),
   5537      hl('DoubleQuotedBody', '0X'),
   5538      hl('DoubleQuote', '"'),
   5539    })
   5540 
   5541    check_parsing('"\\0"', {
   5542      --           0123
   5543      ast = {
   5544        fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\0"'),
   5545      },
   5546    }, {
   5547      hl('DoubleQuote', '"'),
   5548      hl('DoubleQuotedEscape', '\\0'),
   5549      hl('DoubleQuote', '"'),
   5550    })
   5551 
   5552    check_parsing('"\\00"', {
   5553      --           01234
   5554      ast = {
   5555        fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\00"'),
   5556      },
   5557    }, {
   5558      hl('DoubleQuote', '"'),
   5559      hl('DoubleQuotedEscape', '\\00'),
   5560      hl('DoubleQuote', '"'),
   5561    })
   5562 
   5563    check_parsing('"\\000"', {
   5564      --           012345
   5565      ast = {
   5566        fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\000"'),
   5567      },
   5568    }, {
   5569      hl('DoubleQuote', '"'),
   5570      hl('DoubleQuotedEscape', '\\000'),
   5571      hl('DoubleQuote', '"'),
   5572    })
   5573 
   5574    check_parsing('"\\0000"', {
   5575      --           0123456
   5576      ast = {
   5577        fmtn('DoubleQuotedString', 'val="\\0000"', ':0:0:"\\0000"'),
   5578      },
   5579    }, {
   5580      hl('DoubleQuote', '"'),
   5581      hl('DoubleQuotedEscape', '\\000'),
   5582      hl('DoubleQuotedBody', '0'),
   5583      hl('DoubleQuote', '"'),
   5584    })
   5585 
   5586    check_parsing('"\\8"', {
   5587      --           0123
   5588      ast = {
   5589        fmtn('DoubleQuotedString', 'val="8"', ':0:0:"\\8"'),
   5590      },
   5591    }, {
   5592      hl('DoubleQuote', '"'),
   5593      hl('DoubleQuotedUnknownEscape', '\\8'),
   5594      hl('DoubleQuote', '"'),
   5595    })
   5596 
   5597    check_parsing('"\\08"', {
   5598      --           01234
   5599      ast = {
   5600        fmtn('DoubleQuotedString', 'val="\\0008"', ':0:0:"\\08"'),
   5601      },
   5602    }, {
   5603      hl('DoubleQuote', '"'),
   5604      hl('DoubleQuotedEscape', '\\0'),
   5605      hl('DoubleQuotedBody', '8'),
   5606      hl('DoubleQuote', '"'),
   5607    })
   5608 
   5609    check_parsing('"\\008"', {
   5610      --           012345
   5611      ast = {
   5612        fmtn('DoubleQuotedString', 'val="\\0008"', ':0:0:"\\008"'),
   5613      },
   5614    }, {
   5615      hl('DoubleQuote', '"'),
   5616      hl('DoubleQuotedEscape', '\\00'),
   5617      hl('DoubleQuotedBody', '8'),
   5618      hl('DoubleQuote', '"'),
   5619    })
   5620 
   5621    check_parsing('"\\0008"', {
   5622      --           0123456
   5623      ast = {
   5624        fmtn('DoubleQuotedString', 'val="\\0008"', ':0:0:"\\0008"'),
   5625      },
   5626    }, {
   5627      hl('DoubleQuote', '"'),
   5628      hl('DoubleQuotedEscape', '\\000'),
   5629      hl('DoubleQuotedBody', '8'),
   5630      hl('DoubleQuote', '"'),
   5631    })
   5632 
   5633    check_parsing('"\\777"', {
   5634      --           012345
   5635      ast = {
   5636        fmtn('DoubleQuotedString', 'val="\255"', ':0:0:"\\777"'),
   5637      },
   5638    }, {
   5639      hl('DoubleQuote', '"'),
   5640      hl('DoubleQuotedEscape', '\\777'),
   5641      hl('DoubleQuote', '"'),
   5642    })
   5643 
   5644    check_parsing('"\\050"', {
   5645      --           012345
   5646      ast = {
   5647        fmtn('DoubleQuotedString', 'val="\40"', ':0:0:"\\050"'),
   5648      },
   5649    }, {
   5650      hl('DoubleQuote', '"'),
   5651      hl('DoubleQuotedEscape', '\\050'),
   5652      hl('DoubleQuote', '"'),
   5653    })
   5654 
   5655    check_parsing('"\\<C-u>"', {
   5656      --           012345
   5657      ast = {
   5658        fmtn('DoubleQuotedString', 'val="\\021"', ':0:0:"\\<C-u>"'),
   5659      },
   5660    }, {
   5661      hl('DoubleQuote', '"'),
   5662      hl('DoubleQuotedEscape', '\\<C-u>'),
   5663      hl('DoubleQuote', '"'),
   5664    })
   5665 
   5666    check_parsing('"\\<', {
   5667      --           012
   5668      ast = {
   5669        fmtn('DoubleQuotedString', 'val="<"', ':0:0:"\\<'),
   5670      },
   5671      err = {
   5672        arg = '"\\<',
   5673        msg = 'E114: Missing double quote: %.*s',
   5674      },
   5675    }, {
   5676      hl('InvalidDoubleQuote', '"'),
   5677      hl('InvalidDoubleQuotedUnknownEscape', '\\<'),
   5678    })
   5679 
   5680    check_parsing('"\\<"', {
   5681      --           0123
   5682      ast = {
   5683        fmtn('DoubleQuotedString', 'val="<"', ':0:0:"\\<"'),
   5684      },
   5685    }, {
   5686      hl('DoubleQuote', '"'),
   5687      hl('DoubleQuotedUnknownEscape', '\\<'),
   5688      hl('DoubleQuote', '"'),
   5689    })
   5690 
   5691    check_parsing('"\\<C-u"', {
   5692      --           0123456
   5693      ast = {
   5694        fmtn('DoubleQuotedString', 'val="<C-u"', ':0:0:"\\<C-u"'),
   5695      },
   5696    }, {
   5697      hl('DoubleQuote', '"'),
   5698      hl('DoubleQuotedUnknownEscape', '\\<'),
   5699      hl('DoubleQuotedBody', 'C-u'),
   5700      hl('DoubleQuote', '"'),
   5701    })
   5702  end)
   5703  itp('works with multiplication-like operators', function()
   5704    check_parsing('2+2*2', {
   5705      --           01234
   5706      ast = {
   5707        {
   5708          'BinaryPlus:0:1:+',
   5709          children = {
   5710            'Integer(val=2):0:0:2',
   5711            {
   5712              'Multiplication:0:3:*',
   5713              children = {
   5714                'Integer(val=2):0:2:2',
   5715                'Integer(val=2):0:4:2',
   5716              },
   5717            },
   5718          },
   5719        },
   5720      },
   5721    }, {
   5722      hl('Number', '2'),
   5723      hl('BinaryPlus', '+'),
   5724      hl('Number', '2'),
   5725      hl('Multiplication', '*'),
   5726      hl('Number', '2'),
   5727    })
   5728 
   5729    check_parsing('2+2*', {
   5730      --           0123
   5731      ast = {
   5732        {
   5733          'BinaryPlus:0:1:+',
   5734          children = {
   5735            'Integer(val=2):0:0:2',
   5736            {
   5737              'Multiplication:0:3:*',
   5738              children = {
   5739                'Integer(val=2):0:2:2',
   5740              },
   5741            },
   5742          },
   5743        },
   5744      },
   5745      err = {
   5746        arg = '',
   5747        msg = 'E15: Expected value, got EOC: %.*s',
   5748      },
   5749    }, {
   5750      hl('Number', '2'),
   5751      hl('BinaryPlus', '+'),
   5752      hl('Number', '2'),
   5753      hl('Multiplication', '*'),
   5754    })
   5755 
   5756    check_parsing('2+*2', {
   5757      --           0123
   5758      ast = {
   5759        {
   5760          'BinaryPlus:0:1:+',
   5761          children = {
   5762            'Integer(val=2):0:0:2',
   5763            {
   5764              'Multiplication:0:2:*',
   5765              children = {
   5766                'Missing:0:2:',
   5767                'Integer(val=2):0:3:2',
   5768              },
   5769            },
   5770          },
   5771        },
   5772      },
   5773      err = {
   5774        arg = '*2',
   5775        msg = 'E15: Unexpected multiplication-like operator: %.*s',
   5776      },
   5777    }, {
   5778      hl('Number', '2'),
   5779      hl('BinaryPlus', '+'),
   5780      hl('InvalidMultiplication', '*'),
   5781      hl('Number', '2'),
   5782    })
   5783 
   5784    check_parsing('2+2/2', {
   5785      --           01234
   5786      ast = {
   5787        {
   5788          'BinaryPlus:0:1:+',
   5789          children = {
   5790            'Integer(val=2):0:0:2',
   5791            {
   5792              'Division:0:3:/',
   5793              children = {
   5794                'Integer(val=2):0:2:2',
   5795                'Integer(val=2):0:4:2',
   5796              },
   5797            },
   5798          },
   5799        },
   5800      },
   5801    }, {
   5802      hl('Number', '2'),
   5803      hl('BinaryPlus', '+'),
   5804      hl('Number', '2'),
   5805      hl('Division', '/'),
   5806      hl('Number', '2'),
   5807    })
   5808 
   5809    check_parsing('2+2/', {
   5810      --           0123
   5811      ast = {
   5812        {
   5813          'BinaryPlus:0:1:+',
   5814          children = {
   5815            'Integer(val=2):0:0:2',
   5816            {
   5817              'Division:0:3:/',
   5818              children = {
   5819                'Integer(val=2):0:2:2',
   5820              },
   5821            },
   5822          },
   5823        },
   5824      },
   5825      err = {
   5826        arg = '',
   5827        msg = 'E15: Expected value, got EOC: %.*s',
   5828      },
   5829    }, {
   5830      hl('Number', '2'),
   5831      hl('BinaryPlus', '+'),
   5832      hl('Number', '2'),
   5833      hl('Division', '/'),
   5834    })
   5835 
   5836    check_parsing('2+/2', {
   5837      --           0123
   5838      ast = {
   5839        {
   5840          'BinaryPlus:0:1:+',
   5841          children = {
   5842            'Integer(val=2):0:0:2',
   5843            {
   5844              'Division:0:2:/',
   5845              children = {
   5846                'Missing:0:2:',
   5847                'Integer(val=2):0:3:2',
   5848              },
   5849            },
   5850          },
   5851        },
   5852      },
   5853      err = {
   5854        arg = '/2',
   5855        msg = 'E15: Unexpected multiplication-like operator: %.*s',
   5856      },
   5857    }, {
   5858      hl('Number', '2'),
   5859      hl('BinaryPlus', '+'),
   5860      hl('InvalidDivision', '/'),
   5861      hl('Number', '2'),
   5862    })
   5863 
   5864    check_parsing('2+2%2', {
   5865      --           01234
   5866      ast = {
   5867        {
   5868          'BinaryPlus:0:1:+',
   5869          children = {
   5870            'Integer(val=2):0:0:2',
   5871            {
   5872              'Mod:0:3:%',
   5873              children = {
   5874                'Integer(val=2):0:2:2',
   5875                'Integer(val=2):0:4:2',
   5876              },
   5877            },
   5878          },
   5879        },
   5880      },
   5881    }, {
   5882      hl('Number', '2'),
   5883      hl('BinaryPlus', '+'),
   5884      hl('Number', '2'),
   5885      hl('Mod', '%'),
   5886      hl('Number', '2'),
   5887    })
   5888 
   5889    check_parsing('2+2%', {
   5890      --           0123
   5891      ast = {
   5892        {
   5893          'BinaryPlus:0:1:+',
   5894          children = {
   5895            'Integer(val=2):0:0:2',
   5896            {
   5897              'Mod:0:3:%',
   5898              children = {
   5899                'Integer(val=2):0:2:2',
   5900              },
   5901            },
   5902          },
   5903        },
   5904      },
   5905      err = {
   5906        arg = '',
   5907        msg = 'E15: Expected value, got EOC: %.*s',
   5908      },
   5909    }, {
   5910      hl('Number', '2'),
   5911      hl('BinaryPlus', '+'),
   5912      hl('Number', '2'),
   5913      hl('Mod', '%'),
   5914    })
   5915 
   5916    check_parsing('2+%2', {
   5917      --           0123
   5918      ast = {
   5919        {
   5920          'BinaryPlus:0:1:+',
   5921          children = {
   5922            'Integer(val=2):0:0:2',
   5923            {
   5924              'Mod:0:2:%',
   5925              children = {
   5926                'Missing:0:2:',
   5927                'Integer(val=2):0:3:2',
   5928              },
   5929            },
   5930          },
   5931        },
   5932      },
   5933      err = {
   5934        arg = '%2',
   5935        msg = 'E15: Unexpected multiplication-like operator: %.*s',
   5936      },
   5937    }, {
   5938      hl('Number', '2'),
   5939      hl('BinaryPlus', '+'),
   5940      hl('InvalidMod', '%'),
   5941      hl('Number', '2'),
   5942    })
   5943  end)
   5944  itp('works with -', function()
   5945    check_parsing('@a', {
   5946      ast = {
   5947        'Register(name=a):0:0:@a',
   5948      },
   5949    }, {
   5950      hl('Register', '@a'),
   5951    })
   5952    check_parsing('-@a', {
   5953      ast = {
   5954        {
   5955          'UnaryMinus:0:0:-',
   5956          children = {
   5957            'Register(name=a):0:1:@a',
   5958          },
   5959        },
   5960      },
   5961    }, {
   5962      hl('UnaryMinus', '-'),
   5963      hl('Register', '@a'),
   5964    })
   5965    check_parsing('@a-@b', {
   5966      ast = {
   5967        {
   5968          'BinaryMinus:0:2:-',
   5969          children = {
   5970            'Register(name=a):0:0:@a',
   5971            'Register(name=b):0:3:@b',
   5972          },
   5973        },
   5974      },
   5975    }, {
   5976      hl('Register', '@a'),
   5977      hl('BinaryMinus', '-'),
   5978      hl('Register', '@b'),
   5979    })
   5980    check_parsing('@a-@b-@c', {
   5981      ast = {
   5982        {
   5983          'BinaryMinus:0:5:-',
   5984          children = {
   5985            {
   5986              'BinaryMinus:0:2:-',
   5987              children = {
   5988                'Register(name=a):0:0:@a',
   5989                'Register(name=b):0:3:@b',
   5990              },
   5991            },
   5992            'Register(name=c):0:6:@c',
   5993          },
   5994        },
   5995      },
   5996    }, {
   5997      hl('Register', '@a'),
   5998      hl('BinaryMinus', '-'),
   5999      hl('Register', '@b'),
   6000      hl('BinaryMinus', '-'),
   6001      hl('Register', '@c'),
   6002    })
   6003    check_parsing('-@a-@b', {
   6004      ast = {
   6005        {
   6006          'BinaryMinus:0:3:-',
   6007          children = {
   6008            {
   6009              'UnaryMinus:0:0:-',
   6010              children = {
   6011                'Register(name=a):0:1:@a',
   6012              },
   6013            },
   6014            'Register(name=b):0:4:@b',
   6015          },
   6016        },
   6017      },
   6018    }, {
   6019      hl('UnaryMinus', '-'),
   6020      hl('Register', '@a'),
   6021      hl('BinaryMinus', '-'),
   6022      hl('Register', '@b'),
   6023    })
   6024    check_parsing('-@a--@b', {
   6025      ast = {
   6026        {
   6027          'BinaryMinus:0:3:-',
   6028          children = {
   6029            {
   6030              'UnaryMinus:0:0:-',
   6031              children = {
   6032                'Register(name=a):0:1:@a',
   6033              },
   6034            },
   6035            {
   6036              'UnaryMinus:0:4:-',
   6037              children = {
   6038                'Register(name=b):0:5:@b',
   6039              },
   6040            },
   6041          },
   6042        },
   6043      },
   6044    }, {
   6045      hl('UnaryMinus', '-'),
   6046      hl('Register', '@a'),
   6047      hl('BinaryMinus', '-'),
   6048      hl('UnaryMinus', '-'),
   6049      hl('Register', '@b'),
   6050    })
   6051    check_parsing('-', {
   6052      ast = {
   6053        'UnaryMinus:0:0:-',
   6054      },
   6055      err = {
   6056        arg = '',
   6057        msg = 'E15: Expected value, got EOC: %.*s',
   6058      },
   6059    }, {
   6060      hl('UnaryMinus', '-'),
   6061    })
   6062    check_parsing(' -', {
   6063      ast = {
   6064        'UnaryMinus:0:0: -',
   6065      },
   6066      err = {
   6067        arg = '',
   6068        msg = 'E15: Expected value, got EOC: %.*s',
   6069      },
   6070    }, {
   6071      hl('UnaryMinus', '-', 1),
   6072    })
   6073    check_parsing('@a-  ', {
   6074      ast = {
   6075        {
   6076          'BinaryMinus:0:2:-',
   6077          children = {
   6078            'Register(name=a):0:0:@a',
   6079          },
   6080        },
   6081      },
   6082      err = {
   6083        arg = '',
   6084        msg = 'E15: Expected value, got EOC: %.*s',
   6085      },
   6086    }, {
   6087      hl('Register', '@a'),
   6088      hl('BinaryMinus', '-'),
   6089    })
   6090  end)
   6091  itp('works with logical operators', function()
   6092    check_parsing('a && b || c && d', {
   6093      --           0123456789012345
   6094      --           0         1
   6095      ast = {
   6096        {
   6097          'Or:0:6: ||',
   6098          children = {
   6099            {
   6100              'And:0:1: &&',
   6101              children = {
   6102                'PlainIdentifier(scope=0,ident=a):0:0:a',
   6103                'PlainIdentifier(scope=0,ident=b):0:4: b',
   6104              },
   6105            },
   6106            {
   6107              'And:0:11: &&',
   6108              children = {
   6109                'PlainIdentifier(scope=0,ident=c):0:9: c',
   6110                'PlainIdentifier(scope=0,ident=d):0:14: d',
   6111              },
   6112            },
   6113          },
   6114        },
   6115      },
   6116    }, {
   6117      hl('IdentifierName', 'a'),
   6118      hl('And', '&&', 1),
   6119      hl('IdentifierName', 'b', 1),
   6120      hl('Or', '||', 1),
   6121      hl('IdentifierName', 'c', 1),
   6122      hl('And', '&&', 1),
   6123      hl('IdentifierName', 'd', 1),
   6124    })
   6125 
   6126    check_parsing('&& a', {
   6127      --           0123
   6128      ast = {
   6129        {
   6130          'And:0:0:&&',
   6131          children = {
   6132            'Missing:0:0:',
   6133            'PlainIdentifier(scope=0,ident=a):0:2: a',
   6134          },
   6135        },
   6136      },
   6137      err = {
   6138        arg = '&& a',
   6139        msg = 'E15: Unexpected and operator: %.*s',
   6140      },
   6141    }, {
   6142      hl('InvalidAnd', '&&'),
   6143      hl('IdentifierName', 'a', 1),
   6144    })
   6145 
   6146    check_parsing('|| a', {
   6147      --           0123
   6148      ast = {
   6149        {
   6150          'Or:0:0:||',
   6151          children = {
   6152            'Missing:0:0:',
   6153            'PlainIdentifier(scope=0,ident=a):0:2: a',
   6154          },
   6155        },
   6156      },
   6157      err = {
   6158        arg = '|| a',
   6159        msg = 'E15: Unexpected or operator: %.*s',
   6160      },
   6161    }, {
   6162      hl('InvalidOr', '||'),
   6163      hl('IdentifierName', 'a', 1),
   6164    })
   6165 
   6166    check_parsing('a||', {
   6167      --           012
   6168      ast = {
   6169        {
   6170          'Or:0:1:||',
   6171          children = {
   6172            'PlainIdentifier(scope=0,ident=a):0:0:a',
   6173          },
   6174        },
   6175      },
   6176      err = {
   6177        arg = '',
   6178        msg = 'E15: Expected value, got EOC: %.*s',
   6179      },
   6180    }, {
   6181      hl('IdentifierName', 'a'),
   6182      hl('Or', '||'),
   6183    })
   6184 
   6185    check_parsing('a&&', {
   6186      --           012
   6187      ast = {
   6188        {
   6189          'And:0:1:&&',
   6190          children = {
   6191            'PlainIdentifier(scope=0,ident=a):0:0:a',
   6192          },
   6193        },
   6194      },
   6195      err = {
   6196        arg = '',
   6197        msg = 'E15: Expected value, got EOC: %.*s',
   6198      },
   6199    }, {
   6200      hl('IdentifierName', 'a'),
   6201      hl('And', '&&'),
   6202    })
   6203 
   6204    check_parsing('(&&)', {
   6205      --           0123
   6206      ast = {
   6207        {
   6208          'Nested:0:0:(',
   6209          children = {
   6210            {
   6211              'And:0:1:&&',
   6212              children = {
   6213                'Missing:0:1:',
   6214                'Missing:0:3:',
   6215              },
   6216            },
   6217          },
   6218        },
   6219      },
   6220      err = {
   6221        arg = '&&)',
   6222        msg = 'E15: Unexpected and operator: %.*s',
   6223      },
   6224    }, {
   6225      hl('NestingParenthesis', '('),
   6226      hl('InvalidAnd', '&&'),
   6227      hl('InvalidNestingParenthesis', ')'),
   6228    })
   6229 
   6230    check_parsing('(||)', {
   6231      --           0123
   6232      ast = {
   6233        {
   6234          'Nested:0:0:(',
   6235          children = {
   6236            {
   6237              'Or:0:1:||',
   6238              children = {
   6239                'Missing:0:1:',
   6240                'Missing:0:3:',
   6241              },
   6242            },
   6243          },
   6244        },
   6245      },
   6246      err = {
   6247        arg = '||)',
   6248        msg = 'E15: Unexpected or operator: %.*s',
   6249      },
   6250    }, {
   6251      hl('NestingParenthesis', '('),
   6252      hl('InvalidOr', '||'),
   6253      hl('InvalidNestingParenthesis', ')'),
   6254    })
   6255 
   6256    check_parsing('(a||)', {
   6257      --           01234
   6258      ast = {
   6259        {
   6260          'Nested:0:0:(',
   6261          children = {
   6262            {
   6263              'Or:0:2:||',
   6264              children = {
   6265                'PlainIdentifier(scope=0,ident=a):0:1:a',
   6266                'Missing:0:4:',
   6267              },
   6268            },
   6269          },
   6270        },
   6271      },
   6272      err = {
   6273        arg = ')',
   6274        msg = 'E15: Expected value, got parenthesis: %.*s',
   6275      },
   6276    }, {
   6277      hl('NestingParenthesis', '('),
   6278      hl('IdentifierName', 'a'),
   6279      hl('Or', '||'),
   6280      hl('InvalidNestingParenthesis', ')'),
   6281    })
   6282 
   6283    check_parsing('(a&&)', {
   6284      --           01234
   6285      ast = {
   6286        {
   6287          'Nested:0:0:(',
   6288          children = {
   6289            {
   6290              'And:0:2:&&',
   6291              children = {
   6292                'PlainIdentifier(scope=0,ident=a):0:1:a',
   6293                'Missing:0:4:',
   6294              },
   6295            },
   6296          },
   6297        },
   6298      },
   6299      err = {
   6300        arg = ')',
   6301        msg = 'E15: Expected value, got parenthesis: %.*s',
   6302      },
   6303    }, {
   6304      hl('NestingParenthesis', '('),
   6305      hl('IdentifierName', 'a'),
   6306      hl('And', '&&'),
   6307      hl('InvalidNestingParenthesis', ')'),
   6308    })
   6309 
   6310    check_parsing('(&&a)', {
   6311      --           01234
   6312      ast = {
   6313        {
   6314          'Nested:0:0:(',
   6315          children = {
   6316            {
   6317              'And:0:1:&&',
   6318              children = {
   6319                'Missing:0:1:',
   6320                'PlainIdentifier(scope=0,ident=a):0:3:a',
   6321              },
   6322            },
   6323          },
   6324        },
   6325      },
   6326      err = {
   6327        arg = '&&a)',
   6328        msg = 'E15: Unexpected and operator: %.*s',
   6329      },
   6330    }, {
   6331      hl('NestingParenthesis', '('),
   6332      hl('InvalidAnd', '&&'),
   6333      hl('IdentifierName', 'a'),
   6334      hl('NestingParenthesis', ')'),
   6335    })
   6336 
   6337    check_parsing('(||a)', {
   6338      --           01234
   6339      ast = {
   6340        {
   6341          'Nested:0:0:(',
   6342          children = {
   6343            {
   6344              'Or:0:1:||',
   6345              children = {
   6346                'Missing:0:1:',
   6347                'PlainIdentifier(scope=0,ident=a):0:3:a',
   6348              },
   6349            },
   6350          },
   6351        },
   6352      },
   6353      err = {
   6354        arg = '||a)',
   6355        msg = 'E15: Unexpected or operator: %.*s',
   6356      },
   6357    }, {
   6358      hl('NestingParenthesis', '('),
   6359      hl('InvalidOr', '||'),
   6360      hl('IdentifierName', 'a'),
   6361      hl('NestingParenthesis', ')'),
   6362    })
   6363  end)
   6364  itp('works with &opt', function()
   6365    check_parsing('&', {
   6366      --           0
   6367      ast = {
   6368        'Option(scope=0,ident=):0:0:&',
   6369      },
   6370      err = {
   6371        arg = '&',
   6372        msg = 'E112: Option name missing: %.*s',
   6373      },
   6374    }, {
   6375      hl('InvalidOptionSigil', '&'),
   6376    })
   6377 
   6378    check_parsing('&opt', {
   6379      --           0123
   6380      ast = {
   6381        'Option(scope=0,ident=opt):0:0:&opt',
   6382      },
   6383    }, {
   6384      hl('OptionSigil', '&'),
   6385      hl('OptionName', 'opt'),
   6386    })
   6387 
   6388    check_parsing('&l:opt', {
   6389      --           012345
   6390      ast = {
   6391        'Option(scope=l,ident=opt):0:0:&l:opt',
   6392      },
   6393    }, {
   6394      hl('OptionSigil', '&'),
   6395      hl('OptionScope', 'l'),
   6396      hl('OptionScopeDelimiter', ':'),
   6397      hl('OptionName', 'opt'),
   6398    })
   6399 
   6400    check_parsing('&g:opt', {
   6401      --           012345
   6402      ast = {
   6403        'Option(scope=g,ident=opt):0:0:&g:opt',
   6404      },
   6405    }, {
   6406      hl('OptionSigil', '&'),
   6407      hl('OptionScope', 'g'),
   6408      hl('OptionScopeDelimiter', ':'),
   6409      hl('OptionName', 'opt'),
   6410    })
   6411 
   6412    check_parsing('&s:opt', {
   6413      --           012345
   6414      ast = {
   6415        {
   6416          'Colon:0:2::',
   6417          children = {
   6418            'Option(scope=0,ident=s):0:0:&s',
   6419            'PlainIdentifier(scope=0,ident=opt):0:3:opt',
   6420          },
   6421        },
   6422      },
   6423      err = {
   6424        arg = ':opt',
   6425        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   6426      },
   6427    }, {
   6428      hl('OptionSigil', '&'),
   6429      hl('OptionName', 's'),
   6430      hl('InvalidColon', ':'),
   6431      hl('IdentifierName', 'opt'),
   6432    })
   6433 
   6434    check_parsing('& ', {
   6435      --           01
   6436      ast = {
   6437        'Option(scope=0,ident=):0:0:&',
   6438      },
   6439      err = {
   6440        arg = '& ',
   6441        msg = 'E112: Option name missing: %.*s',
   6442      },
   6443    }, {
   6444      hl('InvalidOptionSigil', '&'),
   6445    })
   6446 
   6447    check_parsing('&-', {
   6448      --           01
   6449      ast = {
   6450        {
   6451          'BinaryMinus:0:1:-',
   6452          children = {
   6453            'Option(scope=0,ident=):0:0:&',
   6454          },
   6455        },
   6456      },
   6457      err = {
   6458        arg = '&-',
   6459        msg = 'E112: Option name missing: %.*s',
   6460      },
   6461    }, {
   6462      hl('InvalidOptionSigil', '&'),
   6463      hl('BinaryMinus', '-'),
   6464    })
   6465 
   6466    check_parsing('&A', {
   6467      --           01
   6468      ast = {
   6469        'Option(scope=0,ident=A):0:0:&A',
   6470      },
   6471    }, {
   6472      hl('OptionSigil', '&'),
   6473      hl('OptionName', 'A'),
   6474    })
   6475 
   6476    check_parsing('&xxx_yyy', {
   6477      --           01234567
   6478      ast = {
   6479        {
   6480          'OpMissing:0:4:',
   6481          children = {
   6482            'Option(scope=0,ident=xxx):0:0:&xxx',
   6483            'PlainIdentifier(scope=0,ident=_yyy):0:4:_yyy',
   6484          },
   6485        },
   6486      },
   6487      err = {
   6488        arg = '_yyy',
   6489        msg = 'E15: Missing operator: %.*s',
   6490      },
   6491    }, {
   6492      hl('OptionSigil', '&'),
   6493      hl('OptionName', 'xxx'),
   6494      hl('InvalidIdentifierName', '_yyy'),
   6495    }, {
   6496      [1] = {
   6497        ast = {
   6498          len = 4,
   6499          err = REMOVE_THIS,
   6500          ast = {
   6501            'Option(scope=0,ident=xxx):0:0:&xxx',
   6502          },
   6503        },
   6504        hl_fs = {
   6505          [3] = REMOVE_THIS,
   6506        },
   6507      },
   6508    })
   6509 
   6510    check_parsing('(1+&)', {
   6511      --           01234
   6512      ast = {
   6513        {
   6514          'Nested:0:0:(',
   6515          children = {
   6516            {
   6517              'BinaryPlus:0:2:+',
   6518              children = {
   6519                'Integer(val=1):0:1:1',
   6520                'Option(scope=0,ident=):0:3:&',
   6521              },
   6522            },
   6523          },
   6524        },
   6525      },
   6526      err = {
   6527        arg = '&)',
   6528        msg = 'E112: Option name missing: %.*s',
   6529      },
   6530    }, {
   6531      hl('NestingParenthesis', '('),
   6532      hl('Number', '1'),
   6533      hl('BinaryPlus', '+'),
   6534      hl('InvalidOptionSigil', '&'),
   6535      hl('NestingParenthesis', ')'),
   6536    })
   6537 
   6538    check_parsing('(&+1)', {
   6539      --           01234
   6540      ast = {
   6541        {
   6542          'Nested:0:0:(',
   6543          children = {
   6544            {
   6545              'BinaryPlus:0:2:+',
   6546              children = {
   6547                'Option(scope=0,ident=):0:1:&',
   6548                'Integer(val=1):0:3:1',
   6549              },
   6550            },
   6551          },
   6552        },
   6553      },
   6554      err = {
   6555        arg = '&+1)',
   6556        msg = 'E112: Option name missing: %.*s',
   6557      },
   6558    }, {
   6559      hl('NestingParenthesis', '('),
   6560      hl('InvalidOptionSigil', '&'),
   6561      hl('BinaryPlus', '+'),
   6562      hl('Number', '1'),
   6563      hl('NestingParenthesis', ')'),
   6564    })
   6565  end)
   6566  itp('works with $ENV', function()
   6567    check_parsing('$', {
   6568      --           0
   6569      ast = {
   6570        'Environment(ident=):0:0:$',
   6571      },
   6572      err = {
   6573        arg = '$',
   6574        msg = 'E15: Environment variable name missing',
   6575      },
   6576    }, {
   6577      hl('InvalidEnvironmentSigil', '$'),
   6578    })
   6579 
   6580    check_parsing('$g:A', {
   6581      --           0123
   6582      ast = {
   6583        {
   6584          'Colon:0:2::',
   6585          children = {
   6586            'Environment(ident=g):0:0:$g',
   6587            'PlainIdentifier(scope=0,ident=A):0:3:A',
   6588          },
   6589        },
   6590      },
   6591      err = {
   6592        arg = ':A',
   6593        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   6594      },
   6595    }, {
   6596      hl('EnvironmentSigil', '$'),
   6597      hl('EnvironmentName', 'g'),
   6598      hl('InvalidColon', ':'),
   6599      hl('IdentifierName', 'A'),
   6600    })
   6601 
   6602    check_parsing('$A', {
   6603      --           01
   6604      ast = {
   6605        'Environment(ident=A):0:0:$A',
   6606      },
   6607    }, {
   6608      hl('EnvironmentSigil', '$'),
   6609      hl('EnvironmentName', 'A'),
   6610    })
   6611 
   6612    check_parsing('$ABC', {
   6613      --           0123
   6614      ast = {
   6615        'Environment(ident=ABC):0:0:$ABC',
   6616      },
   6617    }, {
   6618      hl('EnvironmentSigil', '$'),
   6619      hl('EnvironmentName', 'ABC'),
   6620    })
   6621 
   6622    check_parsing('(1+$)', {
   6623      --           01234
   6624      ast = {
   6625        {
   6626          'Nested:0:0:(',
   6627          children = {
   6628            {
   6629              'BinaryPlus:0:2:+',
   6630              children = {
   6631                'Integer(val=1):0:1:1',
   6632                'Environment(ident=):0:3:$',
   6633              },
   6634            },
   6635          },
   6636        },
   6637      },
   6638      err = {
   6639        arg = '$)',
   6640        msg = 'E15: Environment variable name missing',
   6641      },
   6642    }, {
   6643      hl('NestingParenthesis', '('),
   6644      hl('Number', '1'),
   6645      hl('BinaryPlus', '+'),
   6646      hl('InvalidEnvironmentSigil', '$'),
   6647      hl('NestingParenthesis', ')'),
   6648    })
   6649 
   6650    check_parsing('($+1)', {
   6651      --           01234
   6652      ast = {
   6653        {
   6654          'Nested:0:0:(',
   6655          children = {
   6656            {
   6657              'BinaryPlus:0:2:+',
   6658              children = {
   6659                'Environment(ident=):0:1:$',
   6660                'Integer(val=1):0:3:1',
   6661              },
   6662            },
   6663          },
   6664        },
   6665      },
   6666      err = {
   6667        arg = '$+1)',
   6668        msg = 'E15: Environment variable name missing',
   6669      },
   6670    }, {
   6671      hl('NestingParenthesis', '('),
   6672      hl('InvalidEnvironmentSigil', '$'),
   6673      hl('BinaryPlus', '+'),
   6674      hl('Number', '1'),
   6675      hl('NestingParenthesis', ')'),
   6676    })
   6677 
   6678    check_parsing('$_ABC', {
   6679      --           01234
   6680      ast = {
   6681        'Environment(ident=_ABC):0:0:$_ABC',
   6682      },
   6683    }, {
   6684      hl('EnvironmentSigil', '$'),
   6685      hl('EnvironmentName', '_ABC'),
   6686    })
   6687 
   6688    check_parsing('$_', {
   6689      --           01
   6690      ast = {
   6691        'Environment(ident=_):0:0:$_',
   6692      },
   6693    }, {
   6694      hl('EnvironmentSigil', '$'),
   6695      hl('EnvironmentName', '_'),
   6696    })
   6697 
   6698    check_parsing('$ABC_DEF', {
   6699      --           01234567
   6700      ast = {
   6701        'Environment(ident=ABC_DEF):0:0:$ABC_DEF',
   6702      },
   6703    }, {
   6704      hl('EnvironmentSigil', '$'),
   6705      hl('EnvironmentName', 'ABC_DEF'),
   6706    })
   6707  end)
   6708  itp('works with unary !', function()
   6709    check_parsing('!', {
   6710      --           0
   6711      ast = {
   6712        'Not:0:0:!',
   6713      },
   6714      err = {
   6715        arg = '',
   6716        msg = 'E15: Expected value, got EOC: %.*s',
   6717      },
   6718    }, {
   6719      hl('Not', '!'),
   6720    })
   6721 
   6722    check_parsing('!!', {
   6723      --           01
   6724      ast = {
   6725        {
   6726          'Not:0:0:!',
   6727          children = {
   6728            'Not:0:1:!',
   6729          },
   6730        },
   6731      },
   6732      err = {
   6733        arg = '',
   6734        msg = 'E15: Expected value, got EOC: %.*s',
   6735      },
   6736    }, {
   6737      hl('Not', '!'),
   6738      hl('Not', '!'),
   6739    })
   6740 
   6741    check_parsing('!!1', {
   6742      --           012
   6743      ast = {
   6744        {
   6745          'Not:0:0:!',
   6746          children = {
   6747            {
   6748              'Not:0:1:!',
   6749              children = {
   6750                'Integer(val=1):0:2:1',
   6751              },
   6752            },
   6753          },
   6754        },
   6755      },
   6756    }, {
   6757      hl('Not', '!'),
   6758      hl('Not', '!'),
   6759      hl('Number', '1'),
   6760    })
   6761 
   6762    check_parsing('!1', {
   6763      --           01
   6764      ast = {
   6765        {
   6766          'Not:0:0:!',
   6767          children = {
   6768            'Integer(val=1):0:1:1',
   6769          },
   6770        },
   6771      },
   6772    }, {
   6773      hl('Not', '!'),
   6774      hl('Number', '1'),
   6775    })
   6776 
   6777    check_parsing('(!1)', {
   6778      --           0123
   6779      ast = {
   6780        {
   6781          'Nested:0:0:(',
   6782          children = {
   6783            {
   6784              'Not:0:1:!',
   6785              children = {
   6786                'Integer(val=1):0:2:1',
   6787              },
   6788            },
   6789          },
   6790        },
   6791      },
   6792    }, {
   6793      hl('NestingParenthesis', '('),
   6794      hl('Not', '!'),
   6795      hl('Number', '1'),
   6796      hl('NestingParenthesis', ')'),
   6797    })
   6798 
   6799    check_parsing('(!)', {
   6800      --           012
   6801      ast = {
   6802        {
   6803          'Nested:0:0:(',
   6804          children = {
   6805            {
   6806              'Not:0:1:!',
   6807              children = {
   6808                'Missing:0:2:',
   6809              },
   6810            },
   6811          },
   6812        },
   6813      },
   6814      err = {
   6815        arg = ')',
   6816        msg = 'E15: Expected value, got parenthesis: %.*s',
   6817      },
   6818    }, {
   6819      hl('NestingParenthesis', '('),
   6820      hl('Not', '!'),
   6821      hl('InvalidNestingParenthesis', ')'),
   6822    })
   6823 
   6824    check_parsing('(1!2)', {
   6825      --           01234
   6826      ast = {
   6827        {
   6828          'Nested:0:0:(',
   6829          children = {
   6830            {
   6831              'OpMissing:0:2:',
   6832              children = {
   6833                'Integer(val=1):0:1:1',
   6834                {
   6835                  'Not:0:2:!',
   6836                  children = {
   6837                    'Integer(val=2):0:3:2',
   6838                  },
   6839                },
   6840              },
   6841            },
   6842          },
   6843        },
   6844      },
   6845      err = {
   6846        arg = '!2)',
   6847        msg = 'E15: Missing operator: %.*s',
   6848      },
   6849    }, {
   6850      hl('NestingParenthesis', '('),
   6851      hl('Number', '1'),
   6852      hl('InvalidNot', '!'),
   6853      hl('Number', '2'),
   6854      hl('NestingParenthesis', ')'),
   6855    })
   6856 
   6857    check_parsing('1!2', {
   6858      --           012
   6859      ast = {
   6860        {
   6861          'OpMissing:0:1:',
   6862          children = {
   6863            'Integer(val=1):0:0:1',
   6864            {
   6865              'Not:0:1:!',
   6866              children = {
   6867                'Integer(val=2):0:2:2',
   6868              },
   6869            },
   6870          },
   6871        },
   6872      },
   6873      err = {
   6874        arg = '!2',
   6875        msg = 'E15: Missing operator: %.*s',
   6876      },
   6877    }, {
   6878      hl('Number', '1'),
   6879      hl('InvalidNot', '!'),
   6880      hl('Number', '2'),
   6881    }, {
   6882      [1] = {
   6883        ast = {
   6884          len = 1,
   6885          err = REMOVE_THIS,
   6886          ast = {
   6887            'Integer(val=1):0:0:1',
   6888          },
   6889        },
   6890        hl_fs = {
   6891          [2] = REMOVE_THIS,
   6892          [3] = REMOVE_THIS,
   6893        },
   6894      },
   6895    })
   6896  end)
   6897  itp('highlights numbers with prefix', function()
   6898    check_parsing('0xABCDEF', {
   6899      --           01234567
   6900      ast = {
   6901        'Integer(val=11259375):0:0:0xABCDEF',
   6902      },
   6903    }, {
   6904      hl('NumberPrefix', '0x'),
   6905      hl('Number', 'ABCDEF'),
   6906    })
   6907 
   6908    check_parsing('0Xabcdef', {
   6909      --           01234567
   6910      ast = {
   6911        'Integer(val=11259375):0:0:0Xabcdef',
   6912      },
   6913    }, {
   6914      hl('NumberPrefix', '0X'),
   6915      hl('Number', 'abcdef'),
   6916    })
   6917 
   6918    check_parsing('0XABCDEF', {
   6919      --           01234567
   6920      ast = {
   6921        'Integer(val=11259375):0:0:0XABCDEF',
   6922      },
   6923    }, {
   6924      hl('NumberPrefix', '0X'),
   6925      hl('Number', 'ABCDEF'),
   6926    })
   6927 
   6928    check_parsing('0xabcdef', {
   6929      --           01234567
   6930      ast = {
   6931        'Integer(val=11259375):0:0:0xabcdef',
   6932      },
   6933    }, {
   6934      hl('NumberPrefix', '0x'),
   6935      hl('Number', 'abcdef'),
   6936    })
   6937 
   6938    check_parsing('0b001', {
   6939      --           01234
   6940      ast = {
   6941        'Integer(val=1):0:0:0b001',
   6942      },
   6943    }, {
   6944      hl('NumberPrefix', '0b'),
   6945      hl('Number', '001'),
   6946    })
   6947 
   6948    check_parsing('0B001', {
   6949      --           01234
   6950      ast = {
   6951        'Integer(val=1):0:0:0B001',
   6952      },
   6953    }, {
   6954      hl('NumberPrefix', '0B'),
   6955      hl('Number', '001'),
   6956    })
   6957 
   6958    check_parsing('0B00', {
   6959      --           0123
   6960      ast = {
   6961        'Integer(val=0):0:0:0B00',
   6962      },
   6963    }, {
   6964      hl('NumberPrefix', '0B'),
   6965      hl('Number', '00'),
   6966    })
   6967 
   6968    check_parsing('00', {
   6969      --           01
   6970      ast = {
   6971        'Integer(val=0):0:0:00',
   6972      },
   6973    }, {
   6974      hl('NumberPrefix', '0'),
   6975      hl('Number', '0'),
   6976    })
   6977 
   6978    check_parsing('001', {
   6979      --           012
   6980      ast = {
   6981        'Integer(val=1):0:0:001',
   6982      },
   6983    }, {
   6984      hl('NumberPrefix', '0'),
   6985      hl('Number', '01'),
   6986    })
   6987 
   6988    check_parsing('01', {
   6989      --           01
   6990      ast = {
   6991        'Integer(val=1):0:0:01',
   6992      },
   6993    }, {
   6994      hl('NumberPrefix', '0'),
   6995      hl('Number', '1'),
   6996    })
   6997 
   6998    check_parsing('1', {
   6999      --           0
   7000      ast = {
   7001        'Integer(val=1):0:0:1',
   7002      },
   7003    }, {
   7004      hl('Number', '1'),
   7005    })
   7006  end)
   7007  itp('works (KLEE tests)', function()
   7008    check_parsing('\0002&A:\000', {
   7009      len = 0,
   7010      ast = nil,
   7011      err = {
   7012        arg = '\0002&A:\000',
   7013        msg = 'E15: Expected value, got EOC: %.*s',
   7014      },
   7015    }, {}, {
   7016      [2] = {
   7017        ast = {
   7018          len = REMOVE_THIS,
   7019          ast = {
   7020            {
   7021              'Colon:0:4::',
   7022              children = {
   7023                {
   7024                  'OpMissing:0:2:',
   7025                  children = {
   7026                    'Integer(val=2):0:1:2',
   7027                    'Option(scope=0,ident=A):0:2:&A',
   7028                  },
   7029                },
   7030              },
   7031            },
   7032          },
   7033          err = {
   7034            msg = 'E15: Unexpected EOC character: %.*s',
   7035          },
   7036        },
   7037        hl_fs = {
   7038          hl('InvalidSpacing', '\0'),
   7039          hl('Number', '2'),
   7040          hl('InvalidOptionSigil', '&'),
   7041          hl('InvalidOptionName', 'A'),
   7042          hl('InvalidColon', ':'),
   7043          hl('InvalidSpacing', '\0'),
   7044        },
   7045      },
   7046      [3] = {
   7047        ast = {
   7048          len = 2,
   7049          ast = {
   7050            'Integer(val=2):0:1:2',
   7051          },
   7052          err = {
   7053            msg = 'E15: Unexpected EOC character: %.*s',
   7054          },
   7055        },
   7056        hl_fs = {
   7057          hl('InvalidSpacing', '\0'),
   7058          hl('Number', '2'),
   7059        },
   7060      },
   7061    })
   7062    check_parsing({ data = '01', size = 1 }, {
   7063      len = 1,
   7064      ast = {
   7065        'Integer(val=0):0:0:0',
   7066      },
   7067    }, {
   7068      hl('Number', '0'),
   7069    })
   7070    check_parsing({ data = '001', size = 2 }, {
   7071      len = 2,
   7072      ast = {
   7073        'Integer(val=0):0:0:00',
   7074      },
   7075    }, {
   7076      hl('NumberPrefix', '0'),
   7077      hl('Number', '0'),
   7078    })
   7079    check_parsing('"\\U\\', {
   7080      --           0123
   7081      ast = {
   7082        [[DoubleQuotedString(val="U\\"):0:0:"\U\]],
   7083      },
   7084      err = {
   7085        arg = '"\\U\\',
   7086        msg = 'E114: Missing double quote: %.*s',
   7087      },
   7088    }, {
   7089      hl('InvalidDoubleQuote', '"'),
   7090      hl('InvalidDoubleQuotedUnknownEscape', '\\U'),
   7091      hl('InvalidDoubleQuotedBody', '\\'),
   7092    })
   7093    check_parsing('"\\U', {
   7094      --           012
   7095      ast = {
   7096        fmtn('DoubleQuotedString', 'val="U"', ':0:0:"\\U'),
   7097      },
   7098      err = {
   7099        arg = '"\\U',
   7100        msg = 'E114: Missing double quote: %.*s',
   7101      },
   7102    }, {
   7103      hl('InvalidDoubleQuote', '"'),
   7104      hl('InvalidDoubleQuotedUnknownEscape', '\\U'),
   7105    })
   7106    check_parsing('|"\\U\\', {
   7107      --           01234
   7108      len = 0,
   7109      err = {
   7110        arg = '|"\\U\\',
   7111        msg = 'E15: Expected value, got EOC: %.*s',
   7112      },
   7113    }, {}, {
   7114      [2] = {
   7115        ast = {
   7116          len = REMOVE_THIS,
   7117          ast = {
   7118            {
   7119              'Or:0:0:|',
   7120              children = {
   7121                'Missing:0:0:',
   7122                fmtn('DoubleQuotedString', 'val="U\\\\"', ':0:1:"\\U\\'),
   7123              },
   7124            },
   7125          },
   7126          err = {
   7127            msg = 'E15: Unexpected EOC character: %.*s',
   7128          },
   7129        },
   7130        hl_fs = {
   7131          hl('InvalidOr', '|'),
   7132          hl('InvalidDoubleQuote', '"'),
   7133          hl('InvalidDoubleQuotedUnknownEscape', '\\U'),
   7134          hl('InvalidDoubleQuotedBody', '\\'),
   7135        },
   7136      },
   7137    })
   7138    check_parsing('|"\\e"', {
   7139      --           01234
   7140      len = 0,
   7141      err = {
   7142        arg = '|"\\e"',
   7143        msg = 'E15: Expected value, got EOC: %.*s',
   7144      },
   7145    }, {}, {
   7146      [2] = {
   7147        ast = {
   7148          len = REMOVE_THIS,
   7149          ast = {
   7150            {
   7151              'Or:0:0:|',
   7152              children = {
   7153                'Missing:0:0:',
   7154                fmtn('DoubleQuotedString', 'val="\\027"', ':0:1:"\\e"'),
   7155              },
   7156            },
   7157          },
   7158          err = {
   7159            msg = 'E15: Unexpected EOC character: %.*s',
   7160          },
   7161        },
   7162        hl_fs = {
   7163          hl('InvalidOr', '|'),
   7164          hl('DoubleQuote', '"'),
   7165          hl('DoubleQuotedEscape', '\\e'),
   7166          hl('DoubleQuote', '"'),
   7167        },
   7168      },
   7169    })
   7170    check_parsing('|\029', {
   7171      --           01
   7172      len = 0,
   7173      err = {
   7174        arg = '|\029',
   7175        msg = 'E15: Expected value, got EOC: %.*s',
   7176      },
   7177    }, {}, {
   7178      [2] = {
   7179        ast = {
   7180          len = REMOVE_THIS,
   7181          ast = {
   7182            {
   7183              'Or:0:0:|',
   7184              children = {
   7185                'Missing:0:0:',
   7186                'PlainIdentifier(scope=0,ident=\029):0:1:\029',
   7187              },
   7188            },
   7189          },
   7190          err = {
   7191            msg = 'E15: Unexpected EOC character: %.*s',
   7192          },
   7193        },
   7194        hl_fs = {
   7195          hl('InvalidOr', '|'),
   7196          hl('InvalidIdentifierName', '\029'),
   7197        },
   7198      },
   7199    })
   7200    check_parsing('"\\<', {
   7201      --           012
   7202      ast = {
   7203        fmtn('DoubleQuotedString', 'val="<"', ':0:0:"\\<'),
   7204      },
   7205      err = {
   7206        arg = '"\\<',
   7207        msg = 'E114: Missing double quote: %.*s',
   7208      },
   7209    }, {
   7210      hl('InvalidDoubleQuote', '"'),
   7211      hl('InvalidDoubleQuotedUnknownEscape', '\\<'),
   7212    })
   7213    check_parsing('"\\1', {
   7214      --           01 2
   7215      ast = {
   7216        fmtn('DoubleQuotedString', 'val="\\001"', ':0:0:"\\1'),
   7217      },
   7218      err = {
   7219        arg = '"\\1',
   7220        msg = 'E114: Missing double quote: %.*s',
   7221      },
   7222    }, {
   7223      hl('InvalidDoubleQuote', '"'),
   7224      hl('InvalidDoubleQuotedEscape', '\\1'),
   7225    })
   7226    check_parsing('}l', {
   7227      --           01
   7228      ast = {
   7229        {
   7230          'OpMissing:0:1:',
   7231          children = {
   7232            fmtn('UnknownFigure', '---', ':0:0:'),
   7233            'PlainIdentifier(scope=0,ident=l):0:1:l',
   7234          },
   7235        },
   7236      },
   7237      err = {
   7238        arg = '}l',
   7239        msg = 'E15: Unexpected closing figure brace: %.*s',
   7240      },
   7241    }, {
   7242      hl('InvalidFigureBrace', '}'),
   7243      hl('InvalidIdentifierName', 'l'),
   7244    }, {
   7245      [1] = {
   7246        ast = {
   7247          len = 1,
   7248          ast = {
   7249            fmtn('UnknownFigure', '---', ':0:0:'),
   7250          },
   7251        },
   7252        hl_fs = {
   7253          [2] = REMOVE_THIS,
   7254        },
   7255      },
   7256    })
   7257    check_parsing(':?\000\000\000\000\000\000\000', {
   7258      len = 2,
   7259      ast = {
   7260        {
   7261          'Colon:0:0::',
   7262          children = {
   7263            'Missing:0:0:',
   7264            {
   7265              'Ternary:0:1:?',
   7266              children = {
   7267                'Missing:0:1:',
   7268                'TernaryValue:0:1:?',
   7269              },
   7270            },
   7271          },
   7272        },
   7273      },
   7274      err = {
   7275        arg = ':?\000\000\000\000\000\000\000',
   7276        msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
   7277      },
   7278    }, {
   7279      hl('InvalidColon', ':'),
   7280      hl('InvalidTernary', '?'),
   7281    }, {
   7282      [2] = {
   7283        ast = {
   7284          len = REMOVE_THIS,
   7285        },
   7286        hl_fs = {
   7287          [3] = hl('InvalidSpacing', '\0'),
   7288          [4] = hl('InvalidSpacing', '\0'),
   7289          [5] = hl('InvalidSpacing', '\0'),
   7290          [6] = hl('InvalidSpacing', '\0'),
   7291          [7] = hl('InvalidSpacing', '\0'),
   7292          [8] = hl('InvalidSpacing', '\0'),
   7293          [9] = hl('InvalidSpacing', '\0'),
   7294        },
   7295      },
   7296    })
   7297  end)
   7298  itp('works with assignments', function()
   7299    check_asgn_parsing('a=b', {
   7300      --                012
   7301      ast = {
   7302        {
   7303          'Assignment(Plain):0:1:=',
   7304          children = {
   7305            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7306            'PlainIdentifier(scope=0,ident=b):0:2:b',
   7307          },
   7308        },
   7309      },
   7310    }, {
   7311      hl('IdentifierName', 'a'),
   7312      hl('PlainAssignment', '='),
   7313      hl('IdentifierName', 'b'),
   7314    })
   7315 
   7316    check_asgn_parsing('a+=b', {
   7317      --                0123
   7318      ast = {
   7319        {
   7320          'Assignment(Add):0:1:+=',
   7321          children = {
   7322            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7323            'PlainIdentifier(scope=0,ident=b):0:3:b',
   7324          },
   7325        },
   7326      },
   7327    }, {
   7328      hl('IdentifierName', 'a'),
   7329      hl('AssignmentWithAddition', '+='),
   7330      hl('IdentifierName', 'b'),
   7331    })
   7332 
   7333    check_asgn_parsing('a-=b', {
   7334      --                0123
   7335      ast = {
   7336        {
   7337          'Assignment(Subtract):0:1:-=',
   7338          children = {
   7339            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7340            'PlainIdentifier(scope=0,ident=b):0:3:b',
   7341          },
   7342        },
   7343      },
   7344    }, {
   7345      hl('IdentifierName', 'a'),
   7346      hl('AssignmentWithSubtraction', '-='),
   7347      hl('IdentifierName', 'b'),
   7348    })
   7349 
   7350    check_asgn_parsing('a.=b', {
   7351      --                0123
   7352      ast = {
   7353        {
   7354          'Assignment(Concat):0:1:.=',
   7355          children = {
   7356            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7357            'PlainIdentifier(scope=0,ident=b):0:3:b',
   7358          },
   7359        },
   7360      },
   7361    }, {
   7362      hl('IdentifierName', 'a'),
   7363      hl('AssignmentWithConcatenation', '.='),
   7364      hl('IdentifierName', 'b'),
   7365    })
   7366 
   7367    check_asgn_parsing('a', {
   7368      --                0
   7369      ast = {
   7370        'PlainIdentifier(scope=0,ident=a):0:0:a',
   7371      },
   7372    }, {
   7373      hl('IdentifierName', 'a'),
   7374    })
   7375 
   7376    check_asgn_parsing('a b', {
   7377      --                012
   7378      ast = {
   7379        {
   7380          'OpMissing:0:1:',
   7381          children = {
   7382            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7383            'PlainIdentifier(scope=0,ident=b):0:1: b',
   7384          },
   7385        },
   7386      },
   7387      err = {
   7388        arg = 'b',
   7389        msg = 'E15: Expected assignment operator or subscript: %.*s',
   7390      },
   7391    }, {
   7392      hl('IdentifierName', 'a'),
   7393      hl('InvalidSpacing', ' '),
   7394      hl('IdentifierName', 'b'),
   7395    }, {
   7396      [5] = {
   7397        ast = {
   7398          len = 2,
   7399          ast = {
   7400            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7401          },
   7402          err = REMOVE_THIS,
   7403        },
   7404        hl_fs = {
   7405          [2] = REMOVE_THIS,
   7406          [3] = REMOVE_THIS,
   7407        },
   7408      },
   7409    })
   7410 
   7411    check_asgn_parsing('[a, b, c]', {
   7412      --                012345678
   7413      ast = {
   7414        {
   7415          'ListLiteral:0:0:[',
   7416          children = {
   7417            {
   7418              'Comma:0:2:,',
   7419              children = {
   7420                'PlainIdentifier(scope=0,ident=a):0:1:a',
   7421                {
   7422                  'Comma:0:5:,',
   7423                  children = {
   7424                    'PlainIdentifier(scope=0,ident=b):0:3: b',
   7425                    'PlainIdentifier(scope=0,ident=c):0:6: c',
   7426                  },
   7427                },
   7428              },
   7429            },
   7430          },
   7431        },
   7432      },
   7433    }, {
   7434      hl('List', '['),
   7435      hl('IdentifierName', 'a'),
   7436      hl('Comma', ','),
   7437      hl('IdentifierName', 'b', 1),
   7438      hl('Comma', ','),
   7439      hl('IdentifierName', 'c', 1),
   7440      hl('List', ']'),
   7441    })
   7442 
   7443    check_asgn_parsing('[a, b]', {
   7444      --                012345
   7445      ast = {
   7446        {
   7447          'ListLiteral:0:0:[',
   7448          children = {
   7449            {
   7450              'Comma:0:2:,',
   7451              children = {
   7452                'PlainIdentifier(scope=0,ident=a):0:1:a',
   7453                'PlainIdentifier(scope=0,ident=b):0:3: b',
   7454              },
   7455            },
   7456          },
   7457        },
   7458      },
   7459    }, {
   7460      hl('List', '['),
   7461      hl('IdentifierName', 'a'),
   7462      hl('Comma', ','),
   7463      hl('IdentifierName', 'b', 1),
   7464      hl('List', ']'),
   7465    })
   7466 
   7467    check_asgn_parsing('[a]', {
   7468      --                012
   7469      ast = {
   7470        {
   7471          'ListLiteral:0:0:[',
   7472          children = {
   7473            'PlainIdentifier(scope=0,ident=a):0:1:a',
   7474          },
   7475        },
   7476      },
   7477    }, {
   7478      hl('List', '['),
   7479      hl('IdentifierName', 'a'),
   7480      hl('List', ']'),
   7481    })
   7482 
   7483    check_asgn_parsing('[]', {
   7484      --                01
   7485      ast = {
   7486        'ListLiteral:0:0:[',
   7487      },
   7488      err = {
   7489        arg = ']',
   7490        msg = 'E475: Unable to assign to empty list: %.*s',
   7491      },
   7492    }, {
   7493      hl('List', '['),
   7494      hl('InvalidList', ']'),
   7495    })
   7496 
   7497    check_asgn_parsing('a[1] += 3', {
   7498      --                012345678
   7499      ast = {
   7500        {
   7501          'Assignment(Add):0:4: +=',
   7502          children = {
   7503            {
   7504              'Subscript:0:1:[',
   7505              children = {
   7506                'PlainIdentifier(scope=0,ident=a):0:0:a',
   7507                'Integer(val=1):0:2:1',
   7508              },
   7509            },
   7510            'Integer(val=3):0:7: 3',
   7511          },
   7512        },
   7513      },
   7514    }, {
   7515      hl('IdentifierName', 'a'),
   7516      hl('SubscriptBracket', '['),
   7517      hl('Number', '1'),
   7518      hl('SubscriptBracket', ']'),
   7519      hl('AssignmentWithAddition', '+=', 1),
   7520      hl('Number', '3', 1),
   7521    })
   7522 
   7523    check_asgn_parsing('a[1 + 2] += 3', {
   7524      --                0123456789012
   7525      --                0         1
   7526      ast = {
   7527        {
   7528          'Assignment(Add):0:8: +=',
   7529          children = {
   7530            {
   7531              'Subscript:0:1:[',
   7532              children = {
   7533                'PlainIdentifier(scope=0,ident=a):0:0:a',
   7534                {
   7535                  'BinaryPlus:0:3: +',
   7536                  children = {
   7537                    'Integer(val=1):0:2:1',
   7538                    'Integer(val=2):0:5: 2',
   7539                  },
   7540                },
   7541              },
   7542            },
   7543            'Integer(val=3):0:11: 3',
   7544          },
   7545        },
   7546      },
   7547    }, {
   7548      hl('IdentifierName', 'a'),
   7549      hl('SubscriptBracket', '['),
   7550      hl('Number', '1'),
   7551      hl('BinaryPlus', '+', 1),
   7552      hl('Number', '2', 1),
   7553      hl('SubscriptBracket', ']'),
   7554      hl('AssignmentWithAddition', '+=', 1),
   7555      hl('Number', '3', 1),
   7556    })
   7557 
   7558    check_asgn_parsing('a[{-> {b{3}: 4}[5]}()] += 6', {
   7559      --                012345678901234567890123456
   7560      --                0         1         2
   7561      ast = {
   7562        {
   7563          'Assignment(Add):0:22: +=',
   7564          children = {
   7565            {
   7566              'Subscript:0:1:[',
   7567              children = {
   7568                'PlainIdentifier(scope=0,ident=a):0:0:a',
   7569                {
   7570                  'Call:0:19:(',
   7571                  children = {
   7572                    {
   7573                      fmtn('Lambda', '\\di', ':0:2:{'),
   7574                      children = {
   7575                        {
   7576                          'Arrow:0:3:->',
   7577                          children = {
   7578                            {
   7579                              'Subscript:0:15:[',
   7580                              children = {
   7581                                {
   7582                                  fmtn('DictLiteral', '-di', ':0:5: {'),
   7583                                  children = {
   7584                                    {
   7585                                      'Colon:0:11::',
   7586                                      children = {
   7587                                        {
   7588                                          'ComplexIdentifier:0:8:',
   7589                                          children = {
   7590                                            'PlainIdentifier(scope=0,ident=b):0:7:b',
   7591                                            {
   7592                                              fmtn('CurlyBracesIdentifier', '--i', ':0:8:{'),
   7593                                              children = {
   7594                                                'Integer(val=3):0:9:3',
   7595                                              },
   7596                                            },
   7597                                          },
   7598                                        },
   7599                                        'Integer(val=4):0:12: 4',
   7600                                      },
   7601                                    },
   7602                                  },
   7603                                },
   7604                                'Integer(val=5):0:16:5',
   7605                              },
   7606                            },
   7607                          },
   7608                        },
   7609                      },
   7610                    },
   7611                  },
   7612                },
   7613              },
   7614            },
   7615            'Integer(val=6):0:25: 6',
   7616          },
   7617        },
   7618      },
   7619    }, {
   7620      hl('IdentifierName', 'a'),
   7621      hl('SubscriptBracket', '['),
   7622      hl('Lambda', '{'),
   7623      hl('Arrow', '->'),
   7624      hl('Dict', '{', 1),
   7625      hl('IdentifierName', 'b'),
   7626      hl('Curly', '{'),
   7627      hl('Number', '3'),
   7628      hl('Curly', '}'),
   7629      hl('Colon', ':'),
   7630      hl('Number', '4', 1),
   7631      hl('Dict', '}'),
   7632      hl('SubscriptBracket', '['),
   7633      hl('Number', '5'),
   7634      hl('SubscriptBracket', ']'),
   7635      hl('Lambda', '}'),
   7636      hl('CallingParenthesis', '('),
   7637      hl('CallingParenthesis', ')'),
   7638      hl('SubscriptBracket', ']'),
   7639      hl('AssignmentWithAddition', '+=', 1),
   7640      hl('Number', '6', 1),
   7641    })
   7642 
   7643    check_asgn_parsing('a{1}.2[{-> {b{3}: 4}[5]}()]', {
   7644      --                012345678901234567890123456
   7645      --                0         1         2
   7646      ast = {
   7647        {
   7648          'Subscript:0:6:[',
   7649          children = {
   7650            {
   7651              'ConcatOrSubscript:0:4:.',
   7652              children = {
   7653                {
   7654                  'ComplexIdentifier:0:1:',
   7655                  children = {
   7656                    'PlainIdentifier(scope=0,ident=a):0:0:a',
   7657                    {
   7658                      fmtn('CurlyBracesIdentifier', '--i', ':0:1:{'),
   7659                      children = {
   7660                        'Integer(val=1):0:2:1',
   7661                      },
   7662                    },
   7663                  },
   7664                },
   7665                'PlainKey(key=2):0:5:2',
   7666              },
   7667            },
   7668            {
   7669              'Call:0:24:(',
   7670              children = {
   7671                {
   7672                  fmtn('Lambda', '\\di', ':0:7:{'),
   7673                  children = {
   7674                    {
   7675                      'Arrow:0:8:->',
   7676                      children = {
   7677                        {
   7678                          'Subscript:0:20:[',
   7679                          children = {
   7680                            {
   7681                              fmtn('DictLiteral', '-di', ':0:10: {'),
   7682                              children = {
   7683                                {
   7684                                  'Colon:0:16::',
   7685                                  children = {
   7686                                    {
   7687                                      'ComplexIdentifier:0:13:',
   7688                                      children = {
   7689                                        'PlainIdentifier(scope=0,ident=b):0:12:b',
   7690                                        {
   7691                                          fmtn('CurlyBracesIdentifier', '--i', ':0:13:{'),
   7692                                          children = {
   7693                                            'Integer(val=3):0:14:3',
   7694                                          },
   7695                                        },
   7696                                      },
   7697                                    },
   7698                                    'Integer(val=4):0:17: 4',
   7699                                  },
   7700                                },
   7701                              },
   7702                            },
   7703                            'Integer(val=5):0:21:5',
   7704                          },
   7705                        },
   7706                      },
   7707                    },
   7708                  },
   7709                },
   7710              },
   7711            },
   7712          },
   7713        },
   7714      },
   7715    }, {
   7716      hl('IdentifierName', 'a'),
   7717      hl('Curly', '{'),
   7718      hl('Number', '1'),
   7719      hl('Curly', '}'),
   7720      hl('ConcatOrSubscript', '.'),
   7721      hl('IdentifierKey', '2'),
   7722      hl('SubscriptBracket', '['),
   7723      hl('Lambda', '{'),
   7724      hl('Arrow', '->'),
   7725      hl('Dict', '{', 1),
   7726      hl('IdentifierName', 'b'),
   7727      hl('Curly', '{'),
   7728      hl('Number', '3'),
   7729      hl('Curly', '}'),
   7730      hl('Colon', ':'),
   7731      hl('Number', '4', 1),
   7732      hl('Dict', '}'),
   7733      hl('SubscriptBracket', '['),
   7734      hl('Number', '5'),
   7735      hl('SubscriptBracket', ']'),
   7736      hl('Lambda', '}'),
   7737      hl('CallingParenthesis', '('),
   7738      hl('CallingParenthesis', ')'),
   7739      hl('SubscriptBracket', ']'),
   7740    })
   7741 
   7742    check_asgn_parsing('a', {
   7743      --                0
   7744      ast = {
   7745        'PlainIdentifier(scope=0,ident=a):0:0:a',
   7746      },
   7747    }, {
   7748      hl('IdentifierName', 'a'),
   7749    })
   7750 
   7751    check_asgn_parsing('{a}', {
   7752      --                012
   7753      ast = {
   7754        {
   7755          fmtn('CurlyBracesIdentifier', '--i', ':0:0:{'),
   7756          children = {
   7757            'PlainIdentifier(scope=0,ident=a):0:1:a',
   7758          },
   7759        },
   7760      },
   7761    }, {
   7762      hl('FigureBrace', '{'),
   7763      hl('IdentifierName', 'a'),
   7764      hl('Curly', '}'),
   7765    })
   7766 
   7767    check_asgn_parsing('{a}b', {
   7768      --                0123
   7769      ast = {
   7770        {
   7771          'ComplexIdentifier:0:3:',
   7772          children = {
   7773            {
   7774              fmtn('CurlyBracesIdentifier', '--i', ':0:0:{'),
   7775              children = {
   7776                'PlainIdentifier(scope=0,ident=a):0:1:a',
   7777              },
   7778            },
   7779            'PlainIdentifier(scope=0,ident=b):0:3:b',
   7780          },
   7781        },
   7782      },
   7783    }, {
   7784      hl('FigureBrace', '{'),
   7785      hl('IdentifierName', 'a'),
   7786      hl('Curly', '}'),
   7787      hl('IdentifierName', 'b'),
   7788    })
   7789 
   7790    check_asgn_parsing('a{b}c', {
   7791      --                01234
   7792      ast = {
   7793        {
   7794          'ComplexIdentifier:0:1:',
   7795          children = {
   7796            'PlainIdentifier(scope=0,ident=a):0:0:a',
   7797            {
   7798              'ComplexIdentifier:0:4:',
   7799              children = {
   7800                {
   7801                  fmtn('CurlyBracesIdentifier', '--i', ':0:1:{'),
   7802                  children = {
   7803                    'PlainIdentifier(scope=0,ident=b):0:2:b',
   7804                  },
   7805                },
   7806                'PlainIdentifier(scope=0,ident=c):0:4:c',
   7807              },
   7808            },
   7809          },
   7810        },
   7811      },
   7812    }, {
   7813      hl('IdentifierName', 'a'),
   7814      hl('Curly', '{'),
   7815      hl('IdentifierName', 'b'),
   7816      hl('Curly', '}'),
   7817      hl('IdentifierName', 'c'),
   7818    })
   7819 
   7820    check_asgn_parsing('a{b}c[0]', {
   7821      --                01234567
   7822      ast = {
   7823        {
   7824          'Subscript:0:5:[',
   7825          children = {
   7826            {
   7827              'ComplexIdentifier:0:1:',
   7828              children = {
   7829                'PlainIdentifier(scope=0,ident=a):0:0:a',
   7830                {
   7831                  'ComplexIdentifier:0:4:',
   7832                  children = {
   7833                    {
   7834                      fmtn('CurlyBracesIdentifier', '--i', ':0:1:{'),
   7835                      children = {
   7836                        'PlainIdentifier(scope=0,ident=b):0:2:b',
   7837                      },
   7838                    },
   7839                    'PlainIdentifier(scope=0,ident=c):0:4:c',
   7840                  },
   7841                },
   7842              },
   7843            },
   7844            'Integer(val=0):0:6:0',
   7845          },
   7846        },
   7847      },
   7848    }, {
   7849      hl('IdentifierName', 'a'),
   7850      hl('Curly', '{'),
   7851      hl('IdentifierName', 'b'),
   7852      hl('Curly', '}'),
   7853      hl('IdentifierName', 'c'),
   7854      hl('SubscriptBracket', '['),
   7855      hl('Number', '0'),
   7856      hl('SubscriptBracket', ']'),
   7857    })
   7858 
   7859    check_asgn_parsing('a{b}c.0', {
   7860      --                0123456
   7861      ast = {
   7862        {
   7863          'ConcatOrSubscript:0:5:.',
   7864          children = {
   7865            {
   7866              'ComplexIdentifier:0:1:',
   7867              children = {
   7868                'PlainIdentifier(scope=0,ident=a):0:0:a',
   7869                {
   7870                  'ComplexIdentifier:0:4:',
   7871                  children = {
   7872                    {
   7873                      fmtn('CurlyBracesIdentifier', '--i', ':0:1:{'),
   7874                      children = {
   7875                        'PlainIdentifier(scope=0,ident=b):0:2:b',
   7876                      },
   7877                    },
   7878                    'PlainIdentifier(scope=0,ident=c):0:4:c',
   7879                  },
   7880                },
   7881              },
   7882            },
   7883            'PlainKey(key=0):0:6:0',
   7884          },
   7885        },
   7886      },
   7887    }, {
   7888      hl('IdentifierName', 'a'),
   7889      hl('Curly', '{'),
   7890      hl('IdentifierName', 'b'),
   7891      hl('Curly', '}'),
   7892      hl('IdentifierName', 'c'),
   7893      hl('ConcatOrSubscript', '.'),
   7894      hl('IdentifierKey', '0'),
   7895    })
   7896 
   7897    check_asgn_parsing('[a{b}c[0].0]', {
   7898      --                012345678901
   7899      --                0         1
   7900      ast = {
   7901        {
   7902          'ListLiteral:0:0:[',
   7903          children = {
   7904            {
   7905              'ConcatOrSubscript:0:9:.',
   7906              children = {
   7907                {
   7908                  'Subscript:0:6:[',
   7909                  children = {
   7910                    {
   7911                      'ComplexIdentifier:0:2:',
   7912                      children = {
   7913                        'PlainIdentifier(scope=0,ident=a):0:1:a',
   7914                        {
   7915                          'ComplexIdentifier:0:5:',
   7916                          children = {
   7917                            {
   7918                              fmtn('CurlyBracesIdentifier', '--i', ':0:2:{'),
   7919                              children = {
   7920                                'PlainIdentifier(scope=0,ident=b):0:3:b',
   7921                              },
   7922                            },
   7923                            'PlainIdentifier(scope=0,ident=c):0:5:c',
   7924                          },
   7925                        },
   7926                      },
   7927                    },
   7928                    'Integer(val=0):0:7:0',
   7929                  },
   7930                },
   7931                'PlainKey(key=0):0:10:0',
   7932              },
   7933            },
   7934          },
   7935        },
   7936      },
   7937    }, {
   7938      hl('List', '['),
   7939      hl('IdentifierName', 'a'),
   7940      hl('Curly', '{'),
   7941      hl('IdentifierName', 'b'),
   7942      hl('Curly', '}'),
   7943      hl('IdentifierName', 'c'),
   7944      hl('SubscriptBracket', '['),
   7945      hl('Number', '0'),
   7946      hl('SubscriptBracket', ']'),
   7947      hl('ConcatOrSubscript', '.'),
   7948      hl('IdentifierKey', '0'),
   7949      hl('List', ']'),
   7950    })
   7951 
   7952    check_asgn_parsing('{a}{b}', {
   7953      --                012345
   7954      ast = {
   7955        {
   7956          'ComplexIdentifier:0:3:',
   7957          children = {
   7958            {
   7959              fmtn('CurlyBracesIdentifier', '--i', ':0:0:{'),
   7960              children = {
   7961                'PlainIdentifier(scope=0,ident=a):0:1:a',
   7962              },
   7963            },
   7964            {
   7965              fmtn('CurlyBracesIdentifier', '--i', ':0:3:{'),
   7966              children = {
   7967                'PlainIdentifier(scope=0,ident=b):0:4:b',
   7968              },
   7969            },
   7970          },
   7971        },
   7972      },
   7973    }, {
   7974      hl('FigureBrace', '{'),
   7975      hl('IdentifierName', 'a'),
   7976      hl('Curly', '}'),
   7977      hl('Curly', '{'),
   7978      hl('IdentifierName', 'b'),
   7979      hl('Curly', '}'),
   7980    })
   7981 
   7982    check_asgn_parsing('a.b{c}{d}', {
   7983      --                012345678
   7984      ast = {
   7985        {
   7986          'OpMissing:0:3:',
   7987          children = {
   7988            {
   7989              'ConcatOrSubscript:0:1:.',
   7990              children = {
   7991                'PlainIdentifier(scope=0,ident=a):0:0:a',
   7992                'PlainKey(key=b):0:2:b',
   7993              },
   7994            },
   7995            {
   7996              'ComplexIdentifier:0:6:',
   7997              children = {
   7998                {
   7999                  fmtn('CurlyBracesIdentifier', '--i', ':0:3:{'),
   8000                  children = {
   8001                    'PlainIdentifier(scope=0,ident=c):0:4:c',
   8002                  },
   8003                },
   8004                {
   8005                  fmtn('CurlyBracesIdentifier', '--i', ':0:6:{'),
   8006                  children = {
   8007                    'PlainIdentifier(scope=0,ident=d):0:7:d',
   8008                  },
   8009                },
   8010              },
   8011            },
   8012          },
   8013        },
   8014      },
   8015      err = {
   8016        arg = '{c}{d}',
   8017        msg = 'E15: Missing operator: %.*s',
   8018      },
   8019    }, {
   8020      hl('IdentifierName', 'a'),
   8021      hl('ConcatOrSubscript', '.'),
   8022      hl('IdentifierKey', 'b'),
   8023      hl('InvalidFigureBrace', '{'),
   8024      hl('IdentifierName', 'c'),
   8025      hl('Curly', '}'),
   8026      hl('Curly', '{'),
   8027      hl('IdentifierName', 'd'),
   8028      hl('Curly', '}'),
   8029    })
   8030 
   8031    check_asgn_parsing('[a] = 1', {
   8032      --                0123456
   8033      ast = {
   8034        {
   8035          'Assignment(Plain):0:3: =',
   8036          children = {
   8037            {
   8038              'ListLiteral:0:0:[',
   8039              children = {
   8040                'PlainIdentifier(scope=0,ident=a):0:1:a',
   8041              },
   8042            },
   8043            'Integer(val=1):0:5: 1',
   8044          },
   8045        },
   8046      },
   8047    }, {
   8048      hl('List', '['),
   8049      hl('IdentifierName', 'a'),
   8050      hl('List', ']'),
   8051      hl('PlainAssignment', '=', 1),
   8052      hl('Number', '1', 1),
   8053    })
   8054 
   8055    check_asgn_parsing('[a[b], [c, [d, [e]]]] = 1', {
   8056      --                0123456789012345678901234
   8057      --                0         1         2
   8058      ast = {
   8059        {
   8060          'Assignment(Plain):0:21: =',
   8061          children = {
   8062            {
   8063              'ListLiteral:0:0:[',
   8064              children = {
   8065                {
   8066                  'Comma:0:5:,',
   8067                  children = {
   8068                    {
   8069                      'Subscript:0:2:[',
   8070                      children = {
   8071                        'PlainIdentifier(scope=0,ident=a):0:1:a',
   8072                        'PlainIdentifier(scope=0,ident=b):0:3:b',
   8073                      },
   8074                    },
   8075                    {
   8076                      'ListLiteral:0:6: [',
   8077                      children = {
   8078                        {
   8079                          'Comma:0:9:,',
   8080                          children = {
   8081                            'PlainIdentifier(scope=0,ident=c):0:8:c',
   8082                            {
   8083                              'ListLiteral:0:10: [',
   8084                              children = {
   8085                                {
   8086                                  'Comma:0:13:,',
   8087                                  children = {
   8088                                    'PlainIdentifier(scope=0,ident=d):0:12:d',
   8089                                    {
   8090                                      'ListLiteral:0:14: [',
   8091                                      children = {
   8092                                        'PlainIdentifier(scope=0,ident=e):0:16:e',
   8093                                      },
   8094                                    },
   8095                                  },
   8096                                },
   8097                              },
   8098                            },
   8099                          },
   8100                        },
   8101                      },
   8102                    },
   8103                  },
   8104                },
   8105              },
   8106            },
   8107            'Integer(val=1):0:23: 1',
   8108          },
   8109        },
   8110      },
   8111      err = {
   8112        arg = '[c, [d, [e]]]] = 1',
   8113        msg = 'E475: Nested lists not allowed when assigning: %.*s',
   8114      },
   8115    }, {
   8116      hl('List', '['),
   8117      hl('IdentifierName', 'a'),
   8118      hl('SubscriptBracket', '['),
   8119      hl('IdentifierName', 'b'),
   8120      hl('SubscriptBracket', ']'),
   8121      hl('Comma', ','),
   8122      hl('InvalidList', '[', 1),
   8123      hl('IdentifierName', 'c'),
   8124      hl('Comma', ','),
   8125      hl('InvalidList', '[', 1),
   8126      hl('IdentifierName', 'd'),
   8127      hl('Comma', ','),
   8128      hl('InvalidList', '[', 1),
   8129      hl('IdentifierName', 'e'),
   8130      hl('List', ']'),
   8131      hl('List', ']'),
   8132      hl('List', ']'),
   8133      hl('List', ']'),
   8134      hl('PlainAssignment', '=', 1),
   8135      hl('Number', '1', 1),
   8136    })
   8137 
   8138    check_asgn_parsing('$X += 1', {
   8139      --                0123456
   8140      ast = {
   8141        {
   8142          'Assignment(Add):0:2: +=',
   8143          children = {
   8144            'Environment(ident=X):0:0:$X',
   8145            'Integer(val=1):0:5: 1',
   8146          },
   8147        },
   8148      },
   8149    }, {
   8150      hl('EnvironmentSigil', '$'),
   8151      hl('EnvironmentName', 'X'),
   8152      hl('AssignmentWithAddition', '+=', 1),
   8153      hl('Number', '1', 1),
   8154    })
   8155 
   8156    check_asgn_parsing('@a .= 1', {
   8157      --                0123456
   8158      ast = {
   8159        {
   8160          'Assignment(Concat):0:2: .=',
   8161          children = {
   8162            'Register(name=a):0:0:@a',
   8163            'Integer(val=1):0:5: 1',
   8164          },
   8165        },
   8166      },
   8167    }, {
   8168      hl('Register', '@a'),
   8169      hl('AssignmentWithConcatenation', '.=', 1),
   8170      hl('Number', '1', 1),
   8171    })
   8172 
   8173    check_asgn_parsing('&option -= 1', {
   8174      --                012345678901
   8175      --                0         1
   8176      ast = {
   8177        {
   8178          'Assignment(Subtract):0:7: -=',
   8179          children = {
   8180            'Option(scope=0,ident=option):0:0:&option',
   8181            'Integer(val=1):0:10: 1',
   8182          },
   8183        },
   8184      },
   8185    }, {
   8186      hl('OptionSigil', '&'),
   8187      hl('OptionName', 'option'),
   8188      hl('AssignmentWithSubtraction', '-=', 1),
   8189      hl('Number', '1', 1),
   8190    })
   8191 
   8192    check_asgn_parsing('[$X, @a, &l:option] = [1, 2, 3]', {
   8193      --                0123456789012345678901234567890
   8194      --                0         1         2         3
   8195      ast = {
   8196        {
   8197          'Assignment(Plain):0:19: =',
   8198          children = {
   8199            {
   8200              'ListLiteral:0:0:[',
   8201              children = {
   8202                {
   8203                  'Comma:0:3:,',
   8204                  children = {
   8205                    'Environment(ident=X):0:1:$X',
   8206                    {
   8207                      'Comma:0:7:,',
   8208                      children = {
   8209                        'Register(name=a):0:4: @a',
   8210                        'Option(scope=l,ident=option):0:8: &l:option',
   8211                      },
   8212                    },
   8213                  },
   8214                },
   8215              },
   8216            },
   8217            {
   8218              'ListLiteral:0:21: [',
   8219              children = {
   8220                {
   8221                  'Comma:0:24:,',
   8222                  children = {
   8223                    'Integer(val=1):0:23:1',
   8224                    {
   8225                      'Comma:0:27:,',
   8226                      children = {
   8227                        'Integer(val=2):0:25: 2',
   8228                        'Integer(val=3):0:28: 3',
   8229                      },
   8230                    },
   8231                  },
   8232                },
   8233              },
   8234            },
   8235          },
   8236        },
   8237      },
   8238    }, {
   8239      hl('List', '['),
   8240      hl('EnvironmentSigil', '$'),
   8241      hl('EnvironmentName', 'X'),
   8242      hl('Comma', ','),
   8243      hl('Register', '@a', 1),
   8244      hl('Comma', ','),
   8245      hl('OptionSigil', '&', 1),
   8246      hl('OptionScope', 'l'),
   8247      hl('OptionScopeDelimiter', ':'),
   8248      hl('OptionName', 'option'),
   8249      hl('List', ']'),
   8250      hl('PlainAssignment', '=', 1),
   8251      hl('List', '[', 1),
   8252      hl('Number', '1'),
   8253      hl('Comma', ','),
   8254      hl('Number', '2', 1),
   8255      hl('Comma', ','),
   8256      hl('Number', '3', 1),
   8257      hl('List', ']'),
   8258    })
   8259  end)
   8260  itp('works with non-ASCII characters', function()
   8261    check_parsing('"«»"«»', {
   8262      --           013568
   8263      ast = {
   8264        {
   8265          'OpMissing:0:6:',
   8266          children = {
   8267            'DoubleQuotedString(val="«»"):0:0:"«»"',
   8268            {
   8269              'ComplexIdentifier:0:8:',
   8270              children = {
   8271                'PlainIdentifier(scope=0,ident=«):0:6:«',
   8272                'PlainIdentifier(scope=0,ident=»):0:8:»',
   8273              },
   8274            },
   8275          },
   8276        },
   8277      },
   8278      err = {
   8279        arg = '«»',
   8280        msg = 'E15: Unidentified character: %.*s',
   8281      },
   8282    }, {
   8283      hl('DoubleQuote', '"'),
   8284      hl('DoubleQuotedBody', '«»'),
   8285      hl('DoubleQuote', '"'),
   8286      hl('InvalidIdentifierName', '«'),
   8287      hl('InvalidIdentifierName', '»'),
   8288    }, {
   8289      [1] = {
   8290        ast = {
   8291          ast = {
   8292            'DoubleQuotedString(val="«»"):0:0:"«»"',
   8293          },
   8294          len = 6,
   8295        },
   8296        hl_fs = {
   8297          [5] = REMOVE_THIS,
   8298          [4] = REMOVE_THIS,
   8299        },
   8300      },
   8301    })
   8302    check_parsing('"\192"\192"foo"', {
   8303      --           01   23   45678
   8304      ast = {
   8305        {
   8306          'OpMissing:0:3:',
   8307          children = {
   8308            'DoubleQuotedString(val="\192"):0:0:"\192"',
   8309            {
   8310              'OpMissing:0:4:',
   8311              children = {
   8312                'PlainIdentifier(scope=0,ident=\192):0:3:\192',
   8313                'DoubleQuotedString(val="foo"):0:4:"foo"',
   8314              },
   8315            },
   8316          },
   8317        },
   8318      },
   8319      err = {
   8320        arg = '\192"foo"',
   8321        msg = 'E15: Unidentified character: %.*s',
   8322      },
   8323    }, {
   8324      hl('DoubleQuote', '"'),
   8325      hl('DoubleQuotedBody', '\192'),
   8326      hl('DoubleQuote', '"'),
   8327      hl('InvalidIdentifierName', '\192'),
   8328      hl('InvalidDoubleQuote', '"'),
   8329      hl('InvalidDoubleQuotedBody', 'foo'),
   8330      hl('InvalidDoubleQuote', '"'),
   8331    }, {
   8332      [1] = {
   8333        ast = {
   8334          ast = {
   8335            'DoubleQuotedString(val="\192"):0:0:"\192"',
   8336          },
   8337          len = 3,
   8338        },
   8339        hl_fs = {
   8340          [4] = REMOVE_THIS,
   8341          [5] = REMOVE_THIS,
   8342          [6] = REMOVE_THIS,
   8343          [7] = REMOVE_THIS,
   8344        },
   8345      },
   8346    })
   8347  end)
   8348 end