src/abstract-syntax-tree.js
function processIdentifiers(tokenizer, scope) {
  let params = [];

  if (tokenizer.token.match(types.IDENTIFIER)) {
    const keys = [tokenizer.token.value];

    tokenizer.skipToken();

    while (tokenizer.token.match(types.DOT, types.OPEN_SQUARE_BRACKET)) {
      const token = tokenizer.token;

      tokenizer.skipToken();

      const isValidKey = token.match(types.OPEN_SQUARE_BRACKET) ?
        tokenizer.token.match(types.CONSTANT) :
        (
          (tokenizer.token.match(types.CONSTANT) && (typeof tokenizer.token.value === 'number')) ||
          tokenizer.token.match(types.IDENTIFIER)
        );

      if (!isValidKey) {
        throw new SyntaxError('Unexpected object key notation');
      }

      keys.push(tokenizer.token.value);
      tokenizer.skipToken();

      if (token.match(types.OPEN_SQUARE_BRACKET)) {
        if (!tokenizer.token.match(types.CLOSE_SQUARE_BRACKET)) {
          throw new SyntaxError('Closing square bracket expected');
        }

        tokenizer.skipToken();
      }
    }

    const identifier = keys.join('.');

    if (!tokenizer.token.match(types.OPEN_PARENTHESES)) {
      scope.identifiers.push(identifier);

      return createIdentifierNode(identifier);
    }

    params = [];
    tokenizer.skipToken();
    if (!tokenizer.token.match(types.CLOSE_PARENTHESES)) {
      params.push(processLogicalOr(tokenizer, scope));

      while (tokenizer.token.match(types.DELIMITER)) {
        params.push(processLogicalOr(tokenizer.skipToken(), scope));
      }
    }

    if (!tokenizer.token.match(types.CLOSE_PARENTHESES)) {
      throw new SyntaxError('Unexpected end of expression');
    }

    tokenizer.skipToken();
    return createOperatorNode(identifier, params);
  }

  return processConstants(tokenizer, scope);
}
function processIdentifiers(tokenizer, scope) {
  let params = [];

  if (tokenizer.token.match(types.IDENTIFIER)) {
    const keys = [tokenizer.token.value];

    tokenizer.skipToken();

    while (tokenizer.token.match(types.DOT, types.OPEN_SQUARE_BRACKET)) {
      const token = tokenizer.token;

      tokenizer.skipToken();

      const isValidKey = token.match(types.OPEN_SQUARE_BRACKET) ?
        tokenizer.token.match(types.CONSTANT) :
        (
          (tokenizer.token.match(types.CONSTANT) && (typeof tokenizer.token.value === 'number')) ||
          tokenizer.token.match(types.IDENTIFIER)
        );

      if (!isValidKey) {
        throw new SyntaxError('Unexpected object key notation');
      }

      keys.push(tokenizer.token.value);
      tokenizer.skipToken();

      if (token.match(types.OPEN_SQUARE_BRACKET)) {
        if (!tokenizer.token.match(types.CLOSE_SQUARE_BRACKET)) {
          throw new SyntaxError('Closing square bracket expected');
        }

        tokenizer.skipToken();
      }
    }

    const identifier = keys.join('.');

    if (!tokenizer.token.match(types.OPEN_PARENTHESES)) {
      scope.identifiers.push(identifier);

      return createIdentifierNode(identifier);
    }

    params = [];
    tokenizer.skipToken();
    if (!tokenizer.token.match(types.CLOSE_PARENTHESES)) {
      params.push(processLogicalOr(tokenizer, scope));

      while (tokenizer.token.match(types.DELIMITER)) {
        params.push(processLogicalOr(tokenizer.skipToken(), scope));
      }
    }

    if (!tokenizer.token.match(types.CLOSE_PARENTHESES)) {
      throw new SyntaxError('Unexpected end of expression');
    }

    tokenizer.skipToken();
    return createOperatorNode(identifier, params);
  }

  return processConstants(tokenizer, scope);
}
function processIdentifiers ( tokenizer , scope ) { let params = [ ] ; if ( tokenizer . token . match ( types . IDENTIFIER ) ) { const keys = [ tokenizer . token . value ] ; tokenizer . skipToken ( ) ; while ( tokenizer . token . match ( types . DOT , types . OPEN_SQUARE_BRACKET ) ) { const token = tokenizer . token ; tokenizer . skipToken ( ) ; const isValidKey = token . match ( types . OPEN_SQUARE_BRACKET ) ? tokenizer . token . match ( types . CONSTANT ) : ( ( tokenizer . token . match ( types . CONSTANT ) && ( typeof tokenizer . token . value === 'number' ) ) || tokenizer . token . match ( types . IDENTIFIER ) ) ; if ( ! isValidKey ) { throw new SyntaxError ( 'Unexpected object key notation' ) ; } keys . push ( tokenizer . token . value ) ; tokenizer . skipToken ( ) ; if ( token . match ( types . OPEN_SQUARE_BRACKET ) ) { if ( ! tokenizer . token . match ( types . CLOSE_SQUARE_BRACKET ) ) { throw new SyntaxError ( 'Closing square bracket expected' ) ; } tokenizer . skipToken ( ) ; } } const identifier = keys . join ( '.' ) ; if ( ! tokenizer . token . match ( types . OPEN_PARENTHESES ) ) { scope . identifiers . push ( identifier ) ; return createIdentifierNode ( identifier ) ; } params = [ ] ; tokenizer . skipToken ( ) ; if ( ! tokenizer . token . match ( types . CLOSE_PARENTHESES ) ) { params . push ( processLogicalOr ( tokenizer , scope ) ) ; while ( tokenizer . token . match ( types . DELIMITER ) ) { params . push ( processLogicalOr ( tokenizer . skipToken ( ) , scope ) ) ; } } if ( ! tokenizer . token . match ( types . CLOSE_PARENTHESES ) ) { throw new SyntaxError ( 'Unexpected end of expression' ) ; } tokenizer . skipToken ( ) ; return createOperatorNode ( identifier , params ) ; } return processConstants ( tokenizer , scope ) ; }
Process custom identifiers and functions
@return {Function} compiled node
@private
Process custom identifiers and functions