docs: 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);
  }