/* * 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 "parser/scansup.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_TC, STRING, IDENTIFIER, PARAMETER, NOT_EQ, LT_EQ, GT_EQ, DOT_DOT, TYPECAST, PLUS_EQ, EQ_TILDE, LEFT_CONTAINS, RIGHT_CONTAINS, 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_LEFT_CONTAINS: case AG_TOKEN_RIGHT_CONTAINS: 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); }