blob: dcd499dbcf8cd00aa6b4e13ebfd15b861c35b96a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "postgres.h"
#include "nodes/pg_list.h"
#include "parser/scansup.h"
#include "parser/ag_scanner.h"
#include "parser/cypher_gram.h"
#include "parser/cypher_keywords.h"
#include "parser/cypher_parser.h"
int cypher_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, ag_scanner_t scanner)
{
/*
* This list must match ag_token_type.
* 0 means end-of-input.
*/
const int type_map[] = {
0,
INTEGER,
DECIMAL,
STRING,
IDENTIFIER,
PARAMETER,
NOT_EQ,
LT_EQ,
GT_EQ,
DOT_DOT,
TYPECAST,
PLUS_EQ,
EQ_TILDE,
ACCESS_PATH,
ANY_EXISTS,
ALL_EXISTS,
CONCAT
};
ag_token token;
token = ag_scanner_next_token(scanner);
switch (token.type)
{
case AG_TOKEN_NULL:
break;
case AG_TOKEN_INTEGER:
lvalp->integer = token.value.i;
break;
case AG_TOKEN_DECIMAL:
case AG_TOKEN_STRING:
lvalp->string = pstrdup(token.value.s);
break;
case AG_TOKEN_IDENTIFIER:
{
int kwnum;
char *ident;
kwnum = ScanKeywordLookup(token.value.s, &CypherKeyword);
if (kwnum >= 0)
{
/*
* use token.value.s instead of keyword->name to preserve
* case sensitivity
*/
lvalp->keyword = GetScanKeyword(kwnum, &CypherKeyword);
ident = pstrdup(token.value.s);
truncate_identifier(ident, strlen(ident), true);
lvalp->string = ident;
*llocp = token.location;
return CypherKeywordTokens[kwnum];
}
ident = pstrdup(token.value.s);
truncate_identifier(ident, strlen(ident), true);
lvalp->string = ident;
break;
}
case AG_TOKEN_PARAMETER:
lvalp->string = pstrdup(token.value.s);
break;
case AG_TOKEN_LT_GT:
case AG_TOKEN_LT_EQ:
case AG_TOKEN_GT_EQ:
case AG_TOKEN_DOT_DOT:
case AG_TOKEN_PLUS_EQ:
case AG_TOKEN_EQ_TILDE:
case AG_TOKEN_ACCESS_PATH:
case AG_TOKEN_ALL_EXISTS:
case AG_TOKEN_ANY_EXISTS:
case AG_TOKEN_CONCAT:
break;
case AG_TOKEN_TYPECAST:
break;
case AG_TOKEN_CHAR:
*llocp = token.location;
return token.value.c;
default:
ereport(ERROR, (errmsg("unexpected ag_token_type: %d", token.type)));
break;
}
*llocp = token.location;
return type_map[token.type];
}
void cypher_yyerror(YYLTYPE *llocp, ag_scanner_t scanner,
cypher_yy_extra *extra, const char *msg)
{
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
ag_scanner_errmsg(msg, scanner),
ag_scanner_errposition(*llocp, scanner)));
}
/* declaration to make mac os x compiler happy */
int cypher_yyparse(ag_scanner_t scanner, cypher_yy_extra *extra);
List *parse_cypher(const char *s)
{
ag_scanner_t scanner;
cypher_yy_extra extra;
int yyresult;
scanner = ag_scanner_create(s);
extra.result = NIL;
extra.extra = NULL;
yyresult = cypher_yyparse(scanner, &extra);
ag_scanner_destroy(scanner);
/*
* cypher_yyparse() returns 0 if parsing was successful.
* Otherwise, it returns 1 (invalid input) or 2 (memory exhaustion).
*/
if (yyresult)
return NIL;
/*
* Append the extra node regardless of its value. Currently the extra
* node is only used by EXPLAIN
*/
return lappend(extra.result, extra.extra);
}