mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	viml/parser/expressions: Make curly braces name actually work
This commit is contained in:
		@@ -909,6 +909,55 @@ static inline void east_set_error(ExprAST *const ret_ast,
 | 
			
		||||
      } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/// Add identifier which should constitute complex identifier node
 | 
			
		||||
///
 | 
			
		||||
/// This one is to be called only in case want_node is kENodeOperator.
 | 
			
		||||
///
 | 
			
		||||
/// @param  new_ident_node_code  Code used to create a new identifier node and
 | 
			
		||||
///                              update want_node and ast_stack, without
 | 
			
		||||
///                              a trailing semicolon.
 | 
			
		||||
/// @param  hl  Highlighting name to use, passed as an argument to #HL.
 | 
			
		||||
#define ADD_IDENT(new_ident_node_code, hl) \
 | 
			
		||||
    do { \
 | 
			
		||||
      assert(want_node == kENodeOperator); \
 | 
			
		||||
      /* Operator: may only be curly braces name, but only under certain */ \
 | 
			
		||||
      /* conditions. */ \
 | 
			
		||||
\
 | 
			
		||||
      /* First condition is that there is no space before a part of complex */ \
 | 
			
		||||
      /* identifier. */ \
 | 
			
		||||
      if (prev_token.type == kExprLexSpacing) { \
 | 
			
		||||
        OP_MISSING; \
 | 
			
		||||
      } \
 | 
			
		||||
      switch ((*top_node_p)->type) { \
 | 
			
		||||
        /* Second is that previous node is one of the identifiers: */ \
 | 
			
		||||
        /* complex, plain, curly braces. */ \
 | 
			
		||||
\
 | 
			
		||||
        /* TODO(ZyX-I): Extend syntax to allow ${expr}. This is needed to */ \
 | 
			
		||||
        /* handle environment variables like those bash uses for */ \
 | 
			
		||||
        /* `export -f`: their names consist not only of alphanumeric */ \
 | 
			
		||||
        /* characetrs. */ \
 | 
			
		||||
        case kExprNodeComplexIdentifier: \
 | 
			
		||||
        case kExprNodePlainIdentifier: \
 | 
			
		||||
        case kExprNodeCurlyBracesIdentifier: { \
 | 
			
		||||
          NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComplexIdentifier); \
 | 
			
		||||
          cur_node->len = 0; \
 | 
			
		||||
          cur_node->children = *top_node_p; \
 | 
			
		||||
          *top_node_p = cur_node; \
 | 
			
		||||
          kvi_push(ast_stack, &cur_node->children->next); \
 | 
			
		||||
          ExprASTNode **const new_top_node_p = kv_last(ast_stack); \
 | 
			
		||||
          assert(*new_top_node_p == NULL); \
 | 
			
		||||
          new_ident_node_code; \
 | 
			
		||||
          *new_top_node_p = cur_node; \
 | 
			
		||||
          HL_CUR_TOKEN(hl); \
 | 
			
		||||
          break; \
 | 
			
		||||
        } \
 | 
			
		||||
        default: { \
 | 
			
		||||
          OP_MISSING; \
 | 
			
		||||
          break; \
 | 
			
		||||
        } \
 | 
			
		||||
      } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/// Parse one VimL expression
 | 
			
		||||
///
 | 
			
		||||
/// @param  pstate  Parser state.
 | 
			
		||||
@@ -1272,40 +1321,18 @@ viml_pexpr_parse_figure_brace_closing_error:
 | 
			
		||||
            want_node = kENodeArgument;
 | 
			
		||||
            lambda_node = cur_node;
 | 
			
		||||
          } else {
 | 
			
		||||
            // Operator: may only be curly braces name, but only under certain
 | 
			
		||||
            // conditions.
 | 
			
		||||
 | 
			
		||||
            // First condition is that there is no space before {.
 | 
			
		||||
            if (prev_token.type == kExprLexSpacing) {
 | 
			
		||||
              OP_MISSING;
 | 
			
		||||
            }
 | 
			
		||||
            switch ((*top_node_p)->type) {
 | 
			
		||||
              // Second is that previous node is one of the identifiers:
 | 
			
		||||
              // complex, plain, curly braces.
 | 
			
		||||
 | 
			
		||||
              // TODO(ZyX-I): Extend syntax to allow ${expr}. This is needed to
 | 
			
		||||
              // handle environment variables like those bash uses for
 | 
			
		||||
              // `export -f`: their names consist not only of alphanumeric
 | 
			
		||||
              // characetrs.
 | 
			
		||||
              case kExprNodeComplexIdentifier:
 | 
			
		||||
              case kExprNodePlainIdentifier:
 | 
			
		||||
              case kExprNodeCurlyBracesIdentifier: {
 | 
			
		||||
                NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeComplexIdentifier);
 | 
			
		||||
                cur_node->len = 0;
 | 
			
		||||
                viml_pexpr_handle_bop(&ast_stack, cur_node, &want_node);
 | 
			
		||||
                ExprASTNode *const new_top_node = *kv_last(ast_stack);
 | 
			
		||||
                assert(new_top_node->next == NULL);
 | 
			
		||||
                NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCurlyBracesIdentifier);
 | 
			
		||||
                new_top_node->next = cur_node;
 | 
			
		||||
                kvi_push(ast_stack, &cur_node->children);
 | 
			
		||||
                HL_CUR_TOKEN(Curly);
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
              default: {
 | 
			
		||||
                OP_MISSING;
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            ADD_IDENT(
 | 
			
		||||
                do {
 | 
			
		||||
                  NEW_NODE_WITH_CUR_POS(cur_node,
 | 
			
		||||
                                        kExprNodeCurlyBracesIdentifier);
 | 
			
		||||
                  cur_node->data.fig.opening_hl_idx = kv_size(*pstate->colors);
 | 
			
		||||
                  cur_node->data.fig.type_guesses.allow_lambda = false;
 | 
			
		||||
                  cur_node->data.fig.type_guesses.allow_dict = false;
 | 
			
		||||
                  cur_node->data.fig.type_guesses.allow_ident = true;
 | 
			
		||||
                  kvi_push(ast_stack, &cur_node->children);
 | 
			
		||||
                  want_node = kENodeValue;
 | 
			
		||||
                } while (0),
 | 
			
		||||
                Curly);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
@@ -1351,8 +1378,6 @@ viml_pexpr_parse_figure_brace_closing_error:
 | 
			
		||||
          want_node = (want_node == kENodeArgument
 | 
			
		||||
                       ? kENodeArgumentSeparator
 | 
			
		||||
                       : kENodeOperator);
 | 
			
		||||
          // FIXME: It is not valid to have scope inside complex identifier,
 | 
			
		||||
          //        check that.
 | 
			
		||||
          NEW_NODE_WITH_CUR_POS(cur_node, kExprNodePlainIdentifier);
 | 
			
		||||
          cur_node->data.var.scope = cur_token.data.var.scope;
 | 
			
		||||
          const size_t scope_shift = (cur_token.data.var.scope == 0
 | 
			
		||||
@@ -1374,8 +1399,22 @@ viml_pexpr_parse_figure_brace_closing_error:
 | 
			
		||||
                                  cur_token.len - scope_shift,
 | 
			
		||||
                                  HL(Identifier));
 | 
			
		||||
          }
 | 
			
		||||
        // FIXME: Actually, g{foo}g:foo is valid: "1?g{foo}g:foo" is like
 | 
			
		||||
        //        "g{foo}g" and not an error.
 | 
			
		||||
        } else {
 | 
			
		||||
          OP_MISSING;
 | 
			
		||||
          if (cur_token.data.var.scope == 0) {
 | 
			
		||||
            ADD_IDENT(
 | 
			
		||||
                do {
 | 
			
		||||
                  NEW_NODE_WITH_CUR_POS(cur_node, kExprNodePlainIdentifier);
 | 
			
		||||
                  cur_node->data.var.scope = cur_token.data.var.scope;
 | 
			
		||||
                  cur_node->data.var.ident = pline.data + cur_token.start.col;
 | 
			
		||||
                  cur_node->data.var.ident_len = cur_token.len;
 | 
			
		||||
                  want_node = kENodeOperator;
 | 
			
		||||
                } while (0),
 | 
			
		||||
                Identifier);
 | 
			
		||||
          } else {
 | 
			
		||||
            OP_MISSING;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
@@ -1453,7 +1492,8 @@ viml_pexpr_parse_no_paren_closing_error: {}
 | 
			
		||||
              // intentionally inconsistent and he is not very happy with the
 | 
			
		||||
              // situation himself.
 | 
			
		||||
              if ((*top_node_p)->type != kExprNodePlainIdentifier
 | 
			
		||||
                  && (*top_node_p)->type != kExprNodeComplexIdentifier) {
 | 
			
		||||
                  && (*top_node_p)->type != kExprNodeComplexIdentifier
 | 
			
		||||
                  && (*top_node_p)->type != kExprNodeCurlyBracesIdentifier) {
 | 
			
		||||
                OP_MISSING;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -1059,7 +1059,7 @@ describe('Expressions parser', function()
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
    })
 | 
			
		||||
  end)
 | 
			
		||||
  itp('works with identifiers', function()
 | 
			
		||||
  itp('works with variable names, including curly braces ones', function()
 | 
			
		||||
    check_parsing('var', 0, {
 | 
			
		||||
        ast = {
 | 
			
		||||
          'PlainIdentifier(scope=0,ident=var):0:0:var',
 | 
			
		||||
@@ -1084,16 +1084,6 @@ describe('Expressions parser', function()
 | 
			
		||||
      hl('IdentifierScope', 'g'),
 | 
			
		||||
      hl('IdentifierScopeDelimiter', ':'),
 | 
			
		||||
    })
 | 
			
		||||
  end)
 | 
			
		||||
  itp('works with curly braces', function()
 | 
			
		||||
    check_parsing('{}', 0, {
 | 
			
		||||
      ast = {
 | 
			
		||||
        'DictLiteral(-di):0:0:{',
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('Dict', '{'),
 | 
			
		||||
      hl('Dict', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('{a}', 0, {
 | 
			
		||||
      --           012
 | 
			
		||||
      ast = {
 | 
			
		||||
@@ -1167,6 +1157,209 @@ describe('Expressions parser', function()
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('{@a}{@b}', 0, {
 | 
			
		||||
      --           01234567
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'ComplexIdentifier:0:4:',
 | 
			
		||||
          children = {
 | 
			
		||||
            {
 | 
			
		||||
              'CurlyBracesIdentifier(-di):0:0:{',
 | 
			
		||||
              children = {
 | 
			
		||||
                'Register(name=a):0:1:@a',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              'CurlyBracesIdentifier(--i):0:4:{',
 | 
			
		||||
              children = {
 | 
			
		||||
                'Register(name=b):0:5:@b',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@b'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('g:{@a}', 0, {
 | 
			
		||||
      --           01234567
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'ComplexIdentifier:0:2:',
 | 
			
		||||
          children = {
 | 
			
		||||
            'PlainIdentifier(scope=g,ident=):0:0:g:',
 | 
			
		||||
            {
 | 
			
		||||
              'CurlyBracesIdentifier(--i):0:2:{',
 | 
			
		||||
              children = {
 | 
			
		||||
                'Register(name=a):0:3:@a',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('IdentifierScope', 'g'),
 | 
			
		||||
      hl('IdentifierScopeDelimiter', ':'),
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('{@a}_test', 0, {
 | 
			
		||||
      --           012345678
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'ComplexIdentifier:0:4:',
 | 
			
		||||
          children = {
 | 
			
		||||
            {
 | 
			
		||||
              'CurlyBracesIdentifier(-di):0:0:{',
 | 
			
		||||
              children = {
 | 
			
		||||
                'Register(name=a):0:1:@a',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            'PlainIdentifier(scope=0,ident=_test):0:4:_test',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('Identifier', '_test'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('g:{@a}_test', 0, {
 | 
			
		||||
      --           01234567890
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'ComplexIdentifier:0:2:',
 | 
			
		||||
          children = {
 | 
			
		||||
            'PlainIdentifier(scope=g,ident=):0:0:g:',
 | 
			
		||||
            {
 | 
			
		||||
              'ComplexIdentifier:0:6:',
 | 
			
		||||
              children = {
 | 
			
		||||
                {
 | 
			
		||||
                  'CurlyBracesIdentifier(--i):0:2:{',
 | 
			
		||||
                  children = {
 | 
			
		||||
                    'Register(name=a):0:3:@a',
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                'PlainIdentifier(scope=0,ident=_test):0:6:_test',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('IdentifierScope', 'g'),
 | 
			
		||||
      hl('IdentifierScopeDelimiter', ':'),
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('Identifier', '_test'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('g:{@a}_test()', 0, {
 | 
			
		||||
      --           0123456789012
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'Call:0:11:(',
 | 
			
		||||
          children = {
 | 
			
		||||
            {
 | 
			
		||||
              'ComplexIdentifier:0:2:',
 | 
			
		||||
              children = {
 | 
			
		||||
                'PlainIdentifier(scope=g,ident=):0:0:g:',
 | 
			
		||||
                {
 | 
			
		||||
                  'ComplexIdentifier:0:6:',
 | 
			
		||||
                  children = {
 | 
			
		||||
                    {
 | 
			
		||||
                      'CurlyBracesIdentifier(--i):0:2:{',
 | 
			
		||||
                      children = {
 | 
			
		||||
                        'Register(name=a):0:3:@a',
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                    'PlainIdentifier(scope=0,ident=_test):0:6:_test',
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('IdentifierScope', 'g'),
 | 
			
		||||
      hl('IdentifierScopeDelimiter', ':'),
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('Identifier', '_test'),
 | 
			
		||||
      hl('CallingParenthesis', '('),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('{@a} ()', 0, {
 | 
			
		||||
      --           0123456789012
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'Call:0:4: (',
 | 
			
		||||
          children = {
 | 
			
		||||
            {
 | 
			
		||||
              'CurlyBracesIdentifier(-di):0:0:{',
 | 
			
		||||
              children = {
 | 
			
		||||
                'Register(name=a):0:1:@a',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('CallingParenthesis', '(', 1),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('g:{@a} ()', 0, {
 | 
			
		||||
      --           0123456789012
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'Call:0:6: (',
 | 
			
		||||
          children = {
 | 
			
		||||
            {
 | 
			
		||||
              'ComplexIdentifier:0:2:',
 | 
			
		||||
              children = {
 | 
			
		||||
                'PlainIdentifier(scope=g,ident=):0:0:g:',
 | 
			
		||||
                {
 | 
			
		||||
                  'CurlyBracesIdentifier(--i):0:2:{',
 | 
			
		||||
                  children = {
 | 
			
		||||
                    'Register(name=a):0:3:@a',
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('IdentifierScope', 'g'),
 | 
			
		||||
      hl('IdentifierScopeDelimiter', ':'),
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Register', '@a'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('CallingParenthesis', '(', 1),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
    })
 | 
			
		||||
  end)
 | 
			
		||||
  itp('works with lambdas and dictionaries', function()
 | 
			
		||||
    check_parsing('{}', 0, {
 | 
			
		||||
      ast = {
 | 
			
		||||
        'DictLiteral(-di):0:0:{',
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('Dict', '{'),
 | 
			
		||||
      hl('Dict', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('{->@a}', 0, {
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
@@ -1971,8 +2164,175 @@ describe('Expressions parser', function()
 | 
			
		||||
      hl('Comma', ','),
 | 
			
		||||
      hl('Dict', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    check_parsing('{({f -> g})(@h)(@i)}', 0, {
 | 
			
		||||
      --           01234567890123456789
 | 
			
		||||
      --           0         1
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'CurlyBracesIdentifier(-di):0:0:{',
 | 
			
		||||
          children = {
 | 
			
		||||
            {
 | 
			
		||||
              'Call:0:15:(',
 | 
			
		||||
              children = {
 | 
			
		||||
                {
 | 
			
		||||
                  'Call:0:11:(',
 | 
			
		||||
                  children = {
 | 
			
		||||
                    {
 | 
			
		||||
                      'Nested:0:1:(',
 | 
			
		||||
                      children = {
 | 
			
		||||
                        {
 | 
			
		||||
                          'Lambda(\\di):0:2:{',
 | 
			
		||||
                          children = {
 | 
			
		||||
                            'PlainIdentifier(scope=0,ident=f):0:3:f',
 | 
			
		||||
                            {
 | 
			
		||||
                              'Arrow:0:4: ->',
 | 
			
		||||
                              children = {
 | 
			
		||||
                                'PlainIdentifier(scope=0,ident=g):0:7: g',
 | 
			
		||||
                              },
 | 
			
		||||
                            },
 | 
			
		||||
                          },
 | 
			
		||||
                        },
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                    'Register(name=h):0:12:@h',
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                'Register(name=i):0:16:@i',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('NestingParenthesis', '('),
 | 
			
		||||
      hl('Lambda', '{'),
 | 
			
		||||
      hl('Identifier', 'f'),
 | 
			
		||||
      hl('Arrow', '->', 1),
 | 
			
		||||
      hl('Identifier', 'g', 1),
 | 
			
		||||
      hl('Lambda', '}'),
 | 
			
		||||
      hl('NestingParenthesis', ')'),
 | 
			
		||||
      hl('CallingParenthesis', '('),
 | 
			
		||||
      hl('Register', '@h'),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
      hl('CallingParenthesis', '('),
 | 
			
		||||
      hl('Register', '@i'),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
    })
 | 
			
		||||
    -- FIXME the below should not crash
 | 
			
		||||
    check_parsing('a:{{b, c -> @d + @e + ({f -> g})(@h)}(@i)}j', 0, {
 | 
			
		||||
      --           01234567890123456789012345678901234567890123456
 | 
			
		||||
      --           0         1         2         3         4
 | 
			
		||||
      ast = {
 | 
			
		||||
        {
 | 
			
		||||
          'ComplexIdentifier:0:2:',
 | 
			
		||||
          children = {
 | 
			
		||||
            'PlainIdentifier(scope=a,ident=):0:0:g:',
 | 
			
		||||
            {
 | 
			
		||||
              'ComplexIdentifier:0:6:',
 | 
			
		||||
              children = {
 | 
			
		||||
                {
 | 
			
		||||
                  'CurlyBracesIdentifier(--i):0:2:{',
 | 
			
		||||
                  children = {
 | 
			
		||||
                    {
 | 
			
		||||
                      'Call:0:37:(',
 | 
			
		||||
                      children = {
 | 
			
		||||
                        {
 | 
			
		||||
                          'Lambda(\\di):0:3:{',
 | 
			
		||||
                          children = {
 | 
			
		||||
                            {
 | 
			
		||||
                              'Comma:0:5:,',
 | 
			
		||||
                              children = {
 | 
			
		||||
                                'PlainIdentifier(scope=0,ident=b):0:4:b',
 | 
			
		||||
                                'PlainIdentifier(scope=0,ident=c):0:6: c',
 | 
			
		||||
                              },
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                              'Arrow:0:8: ->',
 | 
			
		||||
                              children = {
 | 
			
		||||
                                {
 | 
			
		||||
                                  'BinaryPlus:0:19: +',
 | 
			
		||||
                                  children = {
 | 
			
		||||
                                    {
 | 
			
		||||
                                      'BinaryPlus:0:14: +',
 | 
			
		||||
                                      children = {
 | 
			
		||||
                                        'Register(name=d):0:11: @d',
 | 
			
		||||
                                        'Register(name=e):0:16: @e',
 | 
			
		||||
                                      },
 | 
			
		||||
                                    },
 | 
			
		||||
                                    {
 | 
			
		||||
                                      'Call:0:32:(',
 | 
			
		||||
                                      children = {
 | 
			
		||||
                                        {
 | 
			
		||||
                                          'NestingParenthesis:0:21: (',
 | 
			
		||||
                                          children = {
 | 
			
		||||
                                            {
 | 
			
		||||
                                              'Lambda(\\di):0:23:{',
 | 
			
		||||
                                              children = {
 | 
			
		||||
                                                'PlainIdentifier(scope=0,ident=f):0:24:f',
 | 
			
		||||
                                                {
 | 
			
		||||
                                                  'Arrow:0:25: ->',
 | 
			
		||||
                                                  children = {
 | 
			
		||||
                                                    'PlainIdentifier(scope=0,ident=g):0:28: g',
 | 
			
		||||
                                                  },
 | 
			
		||||
                                                },
 | 
			
		||||
                                              },
 | 
			
		||||
                                            },
 | 
			
		||||
                                          },
 | 
			
		||||
                                        },
 | 
			
		||||
                                        'Register(name=h):0:33:@h',
 | 
			
		||||
                                      },
 | 
			
		||||
                                    },
 | 
			
		||||
                                  },
 | 
			
		||||
                                },
 | 
			
		||||
                              },
 | 
			
		||||
                            },
 | 
			
		||||
                          },
 | 
			
		||||
                        },
 | 
			
		||||
                        'Register(name=i):0:38:@i',
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                    'PlainIdentifier(scope=0,ident=j):0:42:j',
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                'PlainIdentifier(scope=0,ident=_test):0:42:_test',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }, {
 | 
			
		||||
      hl('IdentifierScope', 'a'),
 | 
			
		||||
      hl('IdentifierScopeDelimiter', ':'),
 | 
			
		||||
      hl('Curly', '{'),
 | 
			
		||||
      hl('Lambda', '{'),
 | 
			
		||||
      hl('Identifier', 'b'),
 | 
			
		||||
      hl('Comma', ','),
 | 
			
		||||
      hl('Identifier', 'c', 1),
 | 
			
		||||
      hl('Arrow', '->', 1),
 | 
			
		||||
      hl('Register', '@d', 1),
 | 
			
		||||
      hl('BinaryPlus', '+', 1),
 | 
			
		||||
      hl('Register', '@e', 1),
 | 
			
		||||
      hl('BinaryPlus', '+', 1),
 | 
			
		||||
      hl('NestingParenthesis', '('),
 | 
			
		||||
      hl('Lambda', '{'),
 | 
			
		||||
      hl('Identifier', 'f'),
 | 
			
		||||
      hl('Arrow', '->', 1),
 | 
			
		||||
      hl('Identifier', 'g', 1),
 | 
			
		||||
      hl('Lambda', '}'),
 | 
			
		||||
      hl('NestingParenthesis', ')'),
 | 
			
		||||
      hl('CallingParenthesis', '('),
 | 
			
		||||
      hl('Register', '@h'),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
      hl('Lambda', '}'),
 | 
			
		||||
      hl('CallingParenthesis', '('),
 | 
			
		||||
      hl('Register', '@i'),
 | 
			
		||||
      hl('CallingParenthesis', ')'),
 | 
			
		||||
      hl('Curly', '}'),
 | 
			
		||||
      hl('Identifier', 'j'),
 | 
			
		||||
    })
 | 
			
		||||
  end)
 | 
			
		||||
  -- FIXME: Test sequence of arrows inside and outside lambdas.
 | 
			
		||||
  -- FIXME: Test multiple arguments calling.
 | 
			
		||||
  -- FIXME: Test autoload character and scope in lambda arguments.
 | 
			
		||||
end)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user