text: 
  /*
    +------------------------------------------------------------------------+
    | Phalcon Framework                                                      |
    +------------------------------------------------------------------------+
    | Copyright (c) 2011-2014 Phalcon Team (http://www.phalconphp.com)       |
    +------------------------------------------------------------------------+
    | This source file is subject to the New BSD License that is bundled     |
    | with this package in the file docs/LICENSE.txt.                        |
    |                                                                        |
    | If you did not receive a copy of the license and are unable to         |
    | obtain it through the world-wide-web, please send an email             |
    | to license@phalconphp.com so we can send you a copy immediately.       |
    +------------------------------------------------------------------------+
    | Authors: Andres Gutierrez <andres@phalconphp.com>                      |
    |          Eduar Carvajal <eduar@phalconphp.com>                         |
    +------------------------------------------------------------------------+
  */
  
  const phql_token_names phql_tokens[] =
  {
    { SL("INTEGER"),       PHQL_T_INTEGER },
    { SL("DOUBLE"),        PHQL_T_DOUBLE },
    { SL("STRING"),        PHQL_T_STRING },
    { SL("IDENTIFIER"),    PHQL_T_IDENTIFIER },
    { SL("MINUS"),         PHQL_T_MINUS },
    { SL("+"),             PHQL_T_ADD },
    { SL("-"),             PHQL_T_SUB },
    { SL("*"),             PHQL_T_MUL },
    { SL("/"),             PHQL_T_DIV },
    { SL("&"),             PHQL_T_BITWISE_AND },
    { SL("|"),             PHQL_T_BITWISE_OR },
    { SL("%%"),            PHQL_T_MOD },
    { SL("AND"),           PHQL_T_AND },
    { SL("OR"),            PHQL_T_OR },
    { SL("LIKE"),          PHQL_T_LIKE },
    { SL("ILIKE"),         PHQL_T_ILIKE },
    { SL("DOT"),           PHQL_T_DOT },
    { SL("COLON"),         PHQL_T_COLON },
    { SL("DOUBLECOLON"),   PHQL_T_DOUBLECOLON },
    { SL("COMMA"),         PHQL_T_COMMA },
    { SL("EQUALS"),        PHQL_T_EQUALS },
    { SL("NOT EQUALS"),    PHQL_T_NOTEQUALS },
    { SL("NOT"),           PHQL_T_NOT },
    { SL("<"),             PHQL_T_LESS },
    { SL("<="),            PHQL_T_LESSEQUAL },
    { SL(">"),             PHQL_T_GREATER },
    { SL(">="),            PHQL_T_GREATEREQUAL },
    { SL("@@"),            PHQL_T_TS_MATCHES },
    { SL("||"),            PHQL_T_TS_OR },
    { SL("&&"),            PHQL_T_TS_AND },
    { SL("!!"),            PHQL_T_TS_NEGATE },
    { SL("@>"),            PHQL_T_TS_CONTAINS_ANOTHER },
    { SL("<@"),            PHQL_T_TS_CONTAINS_IN },
    { SL("("),             PHQL_T_PARENTHESES_OPEN },
    { SL(")"),             PHQL_T_PARENTHESES_CLOSE },
    { SL("NUMERIC PLACEHOLDER"), PHQL_T_NPLACEHOLDER },
    { SL("STRING PLACEHOLDER"),  PHQL_T_SPLACEHOLDER },
    { SL("UPDATE"),        PHQL_T_UPDATE },
    { SL("SET"),           PHQL_T_SET },
    { SL("WHERE"),         PHQL_T_WHERE },
    { SL("DELETE"),        PHQL_T_DELETE },
    { SL("FROM"),          PHQL_T_FROM },
    { SL("AS"),            PHQL_T_AS },
    { SL("INSERT"),        PHQL_T_INSERT },
    { SL("INTO"),          PHQL_T_INTO },
    { SL("VALUES"),        PHQL_T_VALUES },
    { SL("SELECT"),        PHQL_T_SELECT },
    { SL("ORDER"),         PHQL_T_ORDER },
    { SL("BY"),            PHQL_T_BY },
    { SL("LIMIT"),         PHQL_T_LIMIT },
    { SL("OFFSET"),        PHQL_T_OFFSET },
    { SL("GROUP"),         PHQL_T_GROUP },
    { SL("HAVING"),        PHQL_T_HAVING },
    { SL("IN"),            PHQL_T_IN },
    { SL("ON"),            PHQL_T_ON },
    { SL("INNER"),         PHQL_T_INNER },
    { SL("JOIN"),          PHQL_T_JOIN },
    { SL("LEFT"),          PHQL_T_LEFT },
    { SL("RIGHT"),         PHQL_T_RIGHT },
    { SL("IS"),            PHQL_T_IS },
    { SL("NULL"),          PHQL_T_NULL },
    { SL("NOT IN"),        PHQL_T_NOTIN },
    { SL("CROSS"),         PHQL_T_CROSS },
    { SL("OUTER"),         PHQL_T_OUTER },
    { SL("FULL"),          PHQL_T_FULL },
    { SL("ASC"),           PHQL_T_ASC },
    { SL("DESC"),          PHQL_T_DESC },
    { SL("BETWEEN"),       PHQL_T_BETWEEN },
    { SL("DISTINCT"),      PHQL_T_DISTINCT },
    { SL("AGAINST"),       PHQL_T_AGAINST },
    { SL("CAST"),          PHQL_T_CAST },
    { SL("CONVERT"),       PHQL_T_CONVERT },
    { SL("USING"),         PHQL_T_USING },
    { SL("ALL"),           PHQL_T_ALL },
    { SL("FOR"),           PHQL_T_FOR },
    { SL("EXISTS"),        PHQL_T_EXISTS },
    { SL("CASE"),          PHQL_T_CASE },
    { SL("WHEN"),          PHQL_T_WHEN },
    { SL("THEN"),          PHQL_T_THEN },
    { SL("ELSE"),          PHQL_T_ELSE },
    { SL("END"),           PHQL_T_END },
    { SL("WITH"),          PHQL_T_WITH },
    { SL("FORCE"),         PHQL_T_FORCE },
    { SL("IGNORE"),        PHQL_T_IGNORE },
    { SL("USE"),           PHQL_T_USE },
    { SL("INDEX"),         PHQL_T_INDEX },
    { NULL, 0, 0 }
  };
  
  static void *phql_wrapper_alloc(size_t bytes){
  	return emalloc(bytes);
  }
  
  static void phql_wrapper_free(void *pointer){
  	efree(pointer);
  }
  
  static void phql_parse_with_token(void* phql_parser, int opcode, int parsercode, phql_scanner_token *token, phql_parser_status *parser_status){
  
  	phql_parser_token *pToken;
  
  	pToken = emalloc(sizeof(phql_parser_token));
  	pToken->opcode = opcode;
  	pToken->token = token->value;
  	pToken->token_len = token->len;
  	pToken->free_flag = 1;
  
  	phql_(phql_parser, parsercode, pToken, parser_status);
  
  	token->value = NULL;
  	token->len = 0;
  }
  
  /**
   * Creates an error message when it's triggered by the scanner
   */
  static void phql_scanner_error_msg(phql_parser_status *parser_status, zval *error_msg){
  
  	char *error = NULL, *error_part;
  	unsigned int length;
  	phql_scanner_state *state = parser_status->scanner_state;
  
  	if (state->start) {
  		length = 64 + state->start_length + parser_status->phql_length;
  		error = emalloc(sizeof(char) * length);
  		if (state->start_length > 16) {
  			error_part = estrndup(state->start, 16);
  			snprintf(error, length, "Scanning error before '%s...' when parsing: %s (%d)", error_part, parser_status->phql, parser_status->phql_length);
  			efree(error_part);
  		} else {
  			snprintf(error, length, "Scanning error before '%s' when parsing: %s (%d)", state->start, parser_status->phql, parser_status->phql_length);
  		}
  		error[length - 1] = '\0';
  		ZVAL_STRING(error_msg, error);
  	} else {
  		ZVAL_STRING(error_msg, "Scanning error near to EOF");
  	}
  
  	if (error) {
  		efree(error);
  	}
  }
  
  /**
   * Executes the internal PHQL parser/tokenizer
   */
  int phql_parse_phql(zval *result, zval *phql) {
  
  	zval error_msg = {};
  
  	if (Z_TYPE_P(phql) != IS_STRING) {
  		PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_model_exception_ce, "PHQL is must be string");
  		return FAILURE;
  	}
  
  	if (phql_internal_parse_phql(result, Z_STRVAL_P(phql), Z_STRLEN_P(phql), &error_msg) == FAILURE) {
  		if (Z_TYPE(error_msg) > IS_NULL) {
  			PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_model_exception_ce, Z_STRVAL(error_msg));
  			zval_ptr_dtor(&error_msg);
  		}
  		else {
  			PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_model_exception_ce, "There was an error parsing PHQL");
  		}
  
  		return FAILURE;
  	}
  
  	return SUCCESS;
  }
  
  /**
   * Executes a PHQL parser/tokenizer
   */
  int phql_internal_parse_phql(zval *result, char *phql, unsigned int phql_length, zval *error_msg) {
  
  	zend_phalcon_globals *phalcon_globals_ptr = PHALCON_VGLOBAL;
  	phql_parser_status *parser_status = NULL;
  	int scanner_status, status = SUCCESS, error_length;
  	phql_scanner_state *state;
  	phql_scanner_token token;
  	void* phql_parser;
  	char *error;
  	zval unique_id = {};
  
  	if (!phql) {
  		ZVAL_STRING(error_msg, "PHQL statement cannot be NULL");
  		return FAILURE;
  	}
  
  	ZVAL_LONG(&unique_id, zend_inline_hash_func(phql, phql_length));
  
  	phalcon_orm_get_prepared_ast(result, &unique_id);
  
  	if (Z_TYPE_P(result) == IS_ARRAY) {
  		return SUCCESS;
  	}
  
  	phql_parser = phql_Alloc(phql_wrapper_alloc);
  	if (unlikely(!phql_parser)) {
  		ZVAL_STRING(error_msg, "Memory allocation error");
  		return FAILURE;
  	}
  
  	parser_status = emalloc(sizeof(phql_parser_status));
  	state = emalloc(sizeof(phql_scanner_state));
  
  	parser_status->status = PHQL_PARSING_OK;
  	parser_status->scanner_state = state;
  	ZVAL_UNDEF(&parser_status->ret);
  	parser_status->syntax_error = NULL;
  	parser_status->token = &token;
  	parser_status->enable_literals = phalcon_globals_ptr->orm.enable_literals;
  	parser_status->phql = phql;
  	parser_status->phql_length = phql_length;
  
  	state->active_token = 0;
  	state->start = phql;
  	state->start_length = 0;
  	state->end = state->start;
  
  	token.value = NULL;
  	token.len = 0;
  
  	while (0 <= (scanner_status = phql_get_token(state, &token))) {
  
  		/* Calculate the 'start' length */
  		state->start_length = (phql + phql_length - state->start);
  		state->active_token = token.opcode;
  
  		/* Parse the token found */
  		switch (token.opcode) {
  			case PHQL_T_IGNORE:
  				break;
  
  			case PHQL_T_ADD:
  				phql_(phql_parser, PHQL_PLUS, NULL, parser_status);
  				break;
  			case PHQL_T_SUB:
  				phql_(phql_parser, PHQL_MINUS, NULL, parser_status);
  				break;
  			case PHQL_T_MUL:
  				phql_(phql_parser, PHQL_TIMES, NULL, parser_status);
  				break;
  			case PHQL_T_DIV:
  				phql_(phql_parser, PHQL_DIVIDE, NULL, parser_status);
  				break;
  			case PHQL_T_MOD:
  				phql_(phql_parser, PHQL_MOD, NULL, parser_status);
  				break;
  			case PHQL_T_AND:
  				phql_(phql_parser, PHQL_AND, NULL, parser_status);
  				break;
  			case PHQL_T_OR:
  				phql_(phql_parser, PHQL_OR, NULL, parser_status);
  				break;
  			case PHQL_T_EQUALS:
  				phql_(phql_parser, PHQL_EQUALS, NULL, parser_status);
  				break;
  			case PHQL_T_NOTEQUALS:
  				phql_(phql_parser, PHQL_NOTEQUALS, NULL, parser_status);
  				break;
  			case PHQL_T_LESS:
  				phql_(phql_parser, PHQL_LESS, NULL, parser_status);
  				break;
  			case PHQL_T_GREATER:
  				phql_(phql_parser, PHQL_GREATER, NULL, parser_status);
  				break;
  			case PHQL_T_GREATEREQUAL:
  				phql_(phql_parser, PHQL_GREATEREQUAL, NULL, parser_status);
  				break;
  			case PHQL_T_LESSEQUAL:
  				phql_(phql_parser, PHQL_LESSEQUAL, NULL, parser_status);
  				break;
  
              case PHQL_T_IDENTIFIER:
      			phql_parse_with_token(phql_parser, PHQL_T_IDENTIFIER, PHQL_IDENTIFIER, &token, parser_status);
      			break;
  
              case PHQL_T_DOT:
      			phql_(phql_parser, PHQL_DOT, NULL, parser_status);
      			break;
      		case PHQL_T_COMMA:
      			phql_(phql_parser, PHQL_COMMA, NULL, parser_status);
      			break;
  
      		case PHQL_T_PARENTHESES_OPEN:
      			phql_(phql_parser, PHQL_PARENTHESES_OPEN, NULL, parser_status);
      			break;
      		case PHQL_T_PARENTHESES_CLOSE:
      			phql_(phql_parser, PHQL_PARENTHESES_CLOSE, NULL, parser_status);
      			break;
  
  			case PHQL_T_LIKE:
  				phql_(phql_parser, PHQL_LIKE, NULL, parser_status);
  				break;
  			case PHQL_T_ILIKE:
  				phql_(phql_parser, PHQL_ILIKE, NULL, parser_status);
  				break;
  			case PHQL_T_NOT:
  				phql_(phql_parser, PHQL_NOT, NULL, parser_status);
  				break;
  			case PHQL_T_BITWISE_AND:
  				phql_(phql_parser, PHQL_BITWISE_AND, NULL, parser_status);
  				break;
  			case PHQL_T_BITWISE_OR:
  				phql_(phql_parser, PHQL_BITWISE_OR, NULL, parser_status);
  				break;
  			case PHQL_T_BITWISE_NOT:
  				phql_(phql_parser, PHQL_BITWISE_NOT, NULL, parser_status);
  				break;
  			case PHQL_T_BITWISE_XOR:
  				phql_(phql_parser, PHQL_BITWISE_XOR, NULL, parser_status);
  				break;
  			case PHQL_T_AGAINST:
  				phql_(phql_parser, PHQL_AGAINST, NULL, parser_status);
  				break;
              case PHQL_T_CASE:
      			phql_(phql_parser, PHQL_CASE, NULL, parser_status);
      			break;
              case PHQL_T_WHEN:
          		phql_(phql_parser, PHQL_WHEN, NULL, parser_status);
          		break;
              case PHQL_T_THEN:
              	phql_(phql_parser, PHQL_THEN, NULL, parser_status);
              	break;
              case PHQL_T_END:
              	phql_(phql_parser, PHQL_END, NULL, parser_status);
              	break;
              case PHQL_T_ELSE:
                  phql_(phql_parser, PHQL_ELSE, NULL, parser_status);
                  break;
  
  			case PHQL_T_INTEGER:
  				if (parser_status->enable_literals) {
  					phql_parse_with_token(phql_parser, PHQL_T_INTEGER, PHQL_INTEGER, &token, parser_status);
  				} else {
  					ZVAL_STRING(error_msg, "Literals are disabled in PHQL statements");
  					parser_status->status = PHQL_PARSING_FAILED;
  				}
  				break;
  			case PHQL_T_DOUBLE:
  				if (parser_status->enable_literals) {
  					phql_parse_with_token(phql_parser, PHQL_T_DOUBLE, PHQL_DOUBLE, &token, parser_status);
  				} else {
  					ZVAL_STRING(error_msg, "Literals are disabled in PHQL statements");
  					parser_status->status = PHQL_PARSING_FAILED;
  				}
  				break;
  			case PHQL_T_STRING:
  				if (parser_status->enable_literals) {
  					phql_parse_with_token(phql_parser, PHQL_T_STRING, PHQL_STRING, &token, parser_status);
  				} else {
  					ZVAL_STRING(error_msg, "Literals are disabled in PHQL statements");
  					parser_status->status = PHQL_PARSING_FAILED;
  				}
  				break;
  			case PHQL_T_TRUE:
  				if (parser_status->enable_literals) {
  					phql_(phql_parser, PHQL_TRUE, NULL, parser_status);
  				} else {
  					ZVAL_STRING(error_msg, "Literals are disabled in PHQL statements");
  					parser_status->status = PHQL_PARSING_FAILED;
  				}
  				break;
  			case PHQL_T_FALSE:
  				if (parser_status->enable_literals) {
  					phql_(phql_parser, PHQL_FALSE, NULL, parser_status);
  				} else {
  					ZVAL_STRING(error_msg, "Literals are disabled in PHQL statements");
  					parser_status->status = PHQL_PARSING_FAILED;
  				}
  				break;
  
  			case PHQL_T_NPLACEHOLDER:
  				phql_parse_with_token(phql_parser, PHQL_T_NPLACEHOLDER, PHQL_NPLACEHOLDER, &token, parser_status);
  				break;
  			case PHQL_T_SPLACEHOLDER:
  				phql_parse_with_token(phql_parser, PHQL_T_SPLACEHOLDER, PHQL_SPLACEHOLDER, &token, parser_status);
  				break;
  			case PHQL_T_BPLACEHOLDER:
  				phql_parse_with_token(phql_parser, PHQL_T_BPLACEHOLDER, PHQL_BPLACEHOLDER, &token, parser_status);
  				break;
  
  			case PHQL_T_FROM:
  				phql_(phql_parser, PHQL_FROM, NULL, parser_status);
  				break;
  			case PHQL_T_UPDATE:
  				phql_(phql_parser, PHQL_UPDATE, NULL, parser_status);
  				break;
  			case PHQL_T_SET:
  				phql_(phql_parser, PHQL_SET, NULL, parser_status);
  				break;
  			case PHQL_T_WHERE:
  				phql_(phql_parser, PHQL_WHERE, NULL, parser_status);
  				break;
  			case PHQL_T_DELETE:
  				phql_(phql_parser, PHQL_DELETE, NULL, parser_status);
  				break;
  			case PHQL_T_INSERT:
  				phql_(phql_parser, PHQL_INSERT, NULL, parser_status);
  				break;
  			case PHQL_T_INTO:
  				phql_(phql_parser, PHQL_INTO, NULL, parser_status);
  				break;
  			case PHQL_T_VALUES:
  				phql_(phql_parser, PHQL_VALUES, NULL, parser_status);
  				break;
  			case PHQL_T_SELECT:
  				phql_(phql_parser, PHQL_SELECT, NULL, parser_status);
  				break;
  			case PHQL_T_AS:
  				phql_(phql_parser, PHQL_AS, NULL, parser_status);
  				break;
  			case PHQL_T_ORDER:
  				phql_(phql_parser, PHQL_ORDER, NULL, parser_status);
  				break;
  			case PHQL_T_BY:
  				phql_(phql_parser, PHQL_BY, NULL, parser_status);
  				break;
  			case PHQL_T_LIMIT:
  				phql_(phql_parser, PHQL_LIMIT, NULL, parser_status);
  				break;
  			case PHQL_T_OFFSET:
  				phql_(phql_parser, PHQL_OFFSET, NULL, parser_status);
  				break;
  			case PHQL_T_GROUP:
  				phql_(phql_parser, PHQL_GROUP, NULL, parser_status);
  				break;
  			case PHQL_T_HAVING:
  				phql_(phql_parser, PHQL_HAVING, NULL, parser_status);
  				break;
  			case PHQL_T_ASC:
  				phql_(phql_parser, PHQL_ASC, NULL, parser_status);
  				break;
  			case PHQL_T_DESC:
  				phql_(phql_parser, PHQL_DESC, NULL, parser_status);
  				break;
  			case PHQL_T_IN:
  				phql_(phql_parser, PHQL_IN, NULL, parser_status);
  				break;
  			case PHQL_T_ON:
  				phql_(phql_parser, PHQL_ON, NULL, parser_status);
  				break;
  			case PHQL_T_INNER:
  				phql_(phql_parser, PHQL_INNER, NULL, parser_status);
  				break;
  			case PHQL_T_JOIN:
  				phql_(phql_parser, PHQL_JOIN, NULL, parser_status);
  				break;
  			case PHQL_T_LEFT:
  				phql_(phql_parser, PHQL_LEFT, NULL, parser_status);
  				break;
  			case PHQL_T_RIGHT:
  				phql_(phql_parser, PHQL_RIGHT, NULL, parser_status);
  				break;
  			case PHQL_T_CROSS:
  				phql_(phql_parser, PHQL_CROSS, NULL, parser_status);
  				break;
  			case PHQL_T_FULL:
  				phql_(phql_parser, PHQL_FULL, NULL, parser_status);
  				break;
  			case PHQL_T_OUTER:
  				phql_(phql_parser, PHQL_OUTER, NULL, parser_status);
  				break;
  			case PHQL_T_IS:
  				phql_(phql_parser, PHQL_IS, NULL, parser_status);
  				break;
  			case PHQL_T_NULL:
  				phql_(phql_parser, PHQL_NULL, NULL, parser_status);
  				break;
  			case PHQL_T_BETWEEN:
  				phql_(phql_parser, PHQL_BETWEEN, NULL, parser_status);
  				break;
  			case PHQL_T_DISTINCT:
  				phql_(phql_parser, PHQL_DISTINCT, NULL, parser_status);
  				break;
  			case PHQL_T_ALL:
  				phql_(phql_parser, PHQL_ALL, NULL, parser_status);
  				break;
  			case PHQL_T_CAST:
  				phql_(phql_parser, PHQL_CAST, NULL, parser_status);
  				break;
  			case PHQL_T_CONVERT:
  				phql_(phql_parser, PHQL_CONVERT, NULL, parser_status);
  				break;
  			case PHQL_T_USING:
  				phql_(phql_parser, PHQL_USING, NULL, parser_status);
  				break;
              case PHQL_T_EXISTS:
      			phql_(phql_parser, PHQL_EXISTS, NULL, parser_status);
      			break;
  			case PHQL_T_TS_MATCHES:
  				phql_(phql_parser, PHQL_TS_MATCHES, NULL, parser_status);
  				break;
  			case PHQL_T_TS_OR:
  				phql_(phql_parser, PHQL_TS_OR, NULL, parser_status);
  				break;
  			case PHQL_T_TS_AND:
  				phql_(phql_parser, PHQL_TS_AND, NULL, parser_status);
  				break;
  			case PHQL_T_TS_NEGATE:
  				phql_(phql_parser, PHQL_TS_NEGATE, NULL, parser_status);
  				break;
  			case PHQL_T_TS_CONTAINS_ANOTHER:
  				phql_(phql_parser, PHQL_TS_CONTAINS_ANOTHER, NULL, parser_status);
  				break;
  			case PHQL_T_TS_CONTAINS_IN:
  				phql_(phql_parser, PHQL_TS_CONTAINS_IN, NULL, parser_status);
  				break;
  			case PHQL_T_FOR:
  				phql_(phql_parser, PHQL_FOR, NULL, parser_status);
  				break;
  			default:
  				parser_status->status = PHQL_PARSING_FAILED;
  				error_length = sizeof(char) * 32;
  				error = emalloc(error_length);
  				snprintf(error, error_length, "Scanner: Unknown opcode %c", token.opcode);
  				error[error_length - 1] = '\0';
  				ZVAL_STRING(error_msg, error);
  				efree(error);
  				break;
  		}
  
  		if (parser_status->status != PHQL_PARSING_OK) {
  			status = FAILURE;
  			break;
  		}
  
  		state->end = state->start;
  	}
  
  	if (status != FAILURE) {
  		switch (scanner_status) {
  			case PHQL_SCANNER_RETCODE_ERR:
  			case PHQL_SCANNER_RETCODE_IMPOSSIBLE:
  				if (Z_TYPE_P(error_msg) <= IS_NULL) {
  					phql_scanner_error_msg(parser_status, error_msg);
  				}
  				status = FAILURE;
  				break;
  			default:
  				phql_(phql_parser, 0, NULL, parser_status);
  		}
  	}
  
  	state->active_token = 0;
  	state->start = NULL;
  
  	if (parser_status->status != PHQL_PARSING_OK) {
  		status = FAILURE;
  		if (parser_status->syntax_error) {
  			if (Z_TYPE_P(error_msg) <= IS_NULL) {
  				ZVAL_STRING(error_msg, parser_status->syntax_error);
  			}
  			efree(parser_status->syntax_error);
  		}
  	}
  
  	phql_Free(phql_parser, phql_wrapper_free);
  
  	if (status != FAILURE) {
  		if (parser_status->status == PHQL_PARSING_OK) {
  			if (Z_TYPE(parser_status->ret) == IS_ARRAY) {
  
  				/**
  				 * Set a unique id for the parsed ast
  				 */
  				if (phalcon_globals_ptr->orm.cache_level >= 1) {
  					add_assoc_long(&parser_status->ret, "id", Z_LVAL(unique_id));
  				}
  
  				ZVAL_COPY_VALUE(result, &parser_status->ret);
  
  				/**
  				 * Store the parsed definition in the cache
  				 */
  				phalcon_orm_set_prepared_ast(&unique_id, result);
  
  			} else {
  				array_init(result);
  			}
  		}
  	}
  
  	efree(parser_status);
  	efree(state);
  
  	return status;
  }
  