mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Cosmetic changes for jsonpath_gram.y and jsonpath_scan.l
This commit include formatting improvements, renamings and comments. Also, it makes jsonpath_scan.l be more uniform with other our lexers. Firstly, states names are renamed to more short alternatives. Secondly, <INITIAL> prefix removed from the rules. Corresponding rules are moved to the tail, so they would anyway work only in initial state. Author: Alexander Korotkov Reviewed-by: John Naylor
This commit is contained in:
parent
d303122eab
commit
8b17298f0b
@ -4,6 +4,8 @@
|
|||||||
* jsonpath_gram.y
|
* jsonpath_gram.y
|
||||||
* Grammar definitions for jsonpath datatype
|
* Grammar definitions for jsonpath datatype
|
||||||
*
|
*
|
||||||
|
* Transforms tokenized jsonpath into tree of JsonPathParseItem structs.
|
||||||
|
*
|
||||||
* Copyright (c) 2019, PostgreSQL Global Development Group
|
* Copyright (c) 2019, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
@ -37,15 +39,17 @@ int jsonpath_yylex(union YYSTYPE *yylval_param);
|
|||||||
int jsonpath_yyparse(JsonPathParseResult **result);
|
int jsonpath_yyparse(JsonPathParseResult **result);
|
||||||
void jsonpath_yyerror(JsonPathParseResult **result, const char *message);
|
void jsonpath_yyerror(JsonPathParseResult **result, const char *message);
|
||||||
|
|
||||||
static JsonPathParseItem *makeItemType(int type);
|
static JsonPathParseItem *makeItemType(JsonPathItemType type);
|
||||||
static JsonPathParseItem *makeItemString(JsonPathString *s);
|
static JsonPathParseItem *makeItemString(JsonPathString *s);
|
||||||
static JsonPathParseItem *makeItemVariable(JsonPathString *s);
|
static JsonPathParseItem *makeItemVariable(JsonPathString *s);
|
||||||
static JsonPathParseItem *makeItemKey(JsonPathString *s);
|
static JsonPathParseItem *makeItemKey(JsonPathString *s);
|
||||||
static JsonPathParseItem *makeItemNumeric(JsonPathString *s);
|
static JsonPathParseItem *makeItemNumeric(JsonPathString *s);
|
||||||
static JsonPathParseItem *makeItemBool(bool val);
|
static JsonPathParseItem *makeItemBool(bool val);
|
||||||
static JsonPathParseItem *makeItemBinary(int type, JsonPathParseItem *la,
|
static JsonPathParseItem *makeItemBinary(JsonPathItemType type,
|
||||||
|
JsonPathParseItem *la,
|
||||||
JsonPathParseItem *ra);
|
JsonPathParseItem *ra);
|
||||||
static JsonPathParseItem *makeItemUnary(int type, JsonPathParseItem *a);
|
static JsonPathParseItem *makeItemUnary(JsonPathItemType type,
|
||||||
|
JsonPathParseItem *a);
|
||||||
static JsonPathParseItem *makeItemList(List *list);
|
static JsonPathParseItem *makeItemList(List *list);
|
||||||
static JsonPathParseItem *makeIndexArray(List *list);
|
static JsonPathParseItem *makeIndexArray(List *list);
|
||||||
static JsonPathParseItem *makeAny(int first, int last);
|
static JsonPathParseItem *makeAny(int first, int last);
|
||||||
@ -75,9 +79,9 @@ static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
|
|||||||
|
|
||||||
%union {
|
%union {
|
||||||
JsonPathString str;
|
JsonPathString str;
|
||||||
List *elems; /* list of JsonPathParseItem */
|
List *elems; /* list of JsonPathParseItem */
|
||||||
List *indexs; /* list of integers */
|
List *indexs; /* list of integers */
|
||||||
JsonPathParseItem *value;
|
JsonPathParseItem *value;
|
||||||
JsonPathParseResult *result;
|
JsonPathParseResult *result;
|
||||||
JsonPathItemType optype;
|
JsonPathItemType optype;
|
||||||
bool boolean;
|
bool boolean;
|
||||||
@ -160,7 +164,7 @@ comp_op:
|
|||||||
;
|
;
|
||||||
|
|
||||||
delimited_predicate:
|
delimited_predicate:
|
||||||
'(' predicate ')' { $$ = $2; }
|
'(' predicate ')' { $$ = $2; }
|
||||||
| EXISTS_P '(' expr ')' { $$ = makeItemUnary(jpiExists, $3); }
|
| EXISTS_P '(' expr ')' { $$ = makeItemUnary(jpiExists, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -170,9 +174,10 @@ predicate:
|
|||||||
| predicate AND_P predicate { $$ = makeItemBinary(jpiAnd, $1, $3); }
|
| predicate AND_P predicate { $$ = makeItemBinary(jpiAnd, $1, $3); }
|
||||||
| predicate OR_P predicate { $$ = makeItemBinary(jpiOr, $1, $3); }
|
| predicate OR_P predicate { $$ = makeItemBinary(jpiOr, $1, $3); }
|
||||||
| NOT_P delimited_predicate { $$ = makeItemUnary(jpiNot, $2); }
|
| NOT_P delimited_predicate { $$ = makeItemUnary(jpiNot, $2); }
|
||||||
| '(' predicate ')' IS_P UNKNOWN_P { $$ = makeItemUnary(jpiIsUnknown, $2); }
|
| '(' predicate ')' IS_P UNKNOWN_P
|
||||||
|
{ $$ = makeItemUnary(jpiIsUnknown, $2); }
|
||||||
| expr STARTS_P WITH_P starts_with_initial
|
| expr STARTS_P WITH_P starts_with_initial
|
||||||
{ $$ = makeItemBinary(jpiStartsWith, $1, $4); }
|
{ $$ = makeItemBinary(jpiStartsWith, $1, $4); }
|
||||||
| expr LIKE_REGEX_P STRING_P { $$ = makeItemLikeRegex($1, &$3, NULL); }
|
| expr LIKE_REGEX_P STRING_P { $$ = makeItemLikeRegex($1, &$3, NULL); }
|
||||||
| expr LIKE_REGEX_P STRING_P FLAG_P STRING_P
|
| expr LIKE_REGEX_P STRING_P FLAG_P STRING_P
|
||||||
{ $$ = makeItemLikeRegex($1, &$3, &$5); }
|
{ $$ = makeItemLikeRegex($1, &$3, &$5); }
|
||||||
@ -232,7 +237,8 @@ any_level:
|
|||||||
any_path:
|
any_path:
|
||||||
ANY_P { $$ = makeAny(0, -1); }
|
ANY_P { $$ = makeAny(0, -1); }
|
||||||
| ANY_P '{' any_level '}' { $$ = makeAny($3, $3); }
|
| ANY_P '{' any_level '}' { $$ = makeAny($3, $3); }
|
||||||
| ANY_P '{' any_level TO_P any_level '}' { $$ = makeAny($3, $5); }
|
| ANY_P '{' any_level TO_P any_level '}'
|
||||||
|
{ $$ = makeAny($3, $5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
accessor_op:
|
accessor_op:
|
||||||
@ -285,10 +291,15 @@ method:
|
|||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
|
|
||||||
static JsonPathParseItem*
|
/*
|
||||||
makeItemType(int type)
|
* The helper functions below allocate and fill JsonPathParseItem's of various
|
||||||
|
* types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static JsonPathParseItem *
|
||||||
|
makeItemType(JsonPathItemType type)
|
||||||
{
|
{
|
||||||
JsonPathParseItem* v = palloc(sizeof(*v));
|
JsonPathParseItem *v = palloc(sizeof(*v));
|
||||||
|
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
|
|
||||||
@ -298,10 +309,10 @@ makeItemType(int type)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JsonPathParseItem*
|
static JsonPathParseItem *
|
||||||
makeItemString(JsonPathString *s)
|
makeItemString(JsonPathString *s)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v;
|
JsonPathParseItem *v;
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
{
|
{
|
||||||
@ -320,7 +331,7 @@ makeItemString(JsonPathString *s)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemVariable(JsonPathString *s)
|
makeItemVariable(JsonPathString *s)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v;
|
JsonPathParseItem *v;
|
||||||
|
|
||||||
v = makeItemType(jpiVariable);
|
v = makeItemType(jpiVariable);
|
||||||
v->value.string.val = s->val;
|
v->value.string.val = s->val;
|
||||||
@ -332,7 +343,7 @@ makeItemVariable(JsonPathString *s)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemKey(JsonPathString *s)
|
makeItemKey(JsonPathString *s)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v;
|
JsonPathParseItem *v;
|
||||||
|
|
||||||
v = makeItemString(s);
|
v = makeItemString(s);
|
||||||
v->type = jpiKey;
|
v->type = jpiKey;
|
||||||
@ -343,7 +354,7 @@ makeItemKey(JsonPathString *s)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemNumeric(JsonPathString *s)
|
makeItemNumeric(JsonPathString *s)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v;
|
JsonPathParseItem *v;
|
||||||
|
|
||||||
v = makeItemType(jpiNumeric);
|
v = makeItemType(jpiNumeric);
|
||||||
v->value.numeric =
|
v->value.numeric =
|
||||||
@ -356,7 +367,7 @@ makeItemNumeric(JsonPathString *s)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemBool(bool val)
|
makeItemBool(bool val)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v = makeItemType(jpiBool);
|
JsonPathParseItem *v = makeItemType(jpiBool);
|
||||||
|
|
||||||
v->value.boolean = val;
|
v->value.boolean = val;
|
||||||
|
|
||||||
@ -364,7 +375,7 @@ makeItemBool(bool val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemBinary(int type, JsonPathParseItem* la, JsonPathParseItem *ra)
|
makeItemBinary(JsonPathItemType type, JsonPathParseItem *la, JsonPathParseItem *ra)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v = makeItemType(type);
|
JsonPathParseItem *v = makeItemType(type);
|
||||||
|
|
||||||
@ -375,7 +386,7 @@ makeItemBinary(int type, JsonPathParseItem* la, JsonPathParseItem *ra)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemUnary(int type, JsonPathParseItem* a)
|
makeItemUnary(JsonPathItemType type, JsonPathParseItem *a)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v;
|
JsonPathParseItem *v;
|
||||||
|
|
||||||
@ -401,8 +412,9 @@ makeItemUnary(int type, JsonPathParseItem* a)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeItemList(List *list)
|
makeItemList(List *list)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *head, *end;
|
JsonPathParseItem *head,
|
||||||
ListCell *cell = list_head(list);
|
*end;
|
||||||
|
ListCell *cell = list_head(list);
|
||||||
|
|
||||||
head = end = (JsonPathParseItem *) lfirst(cell);
|
head = end = (JsonPathParseItem *) lfirst(cell);
|
||||||
|
|
||||||
@ -427,8 +439,8 @@ makeItemList(List *list)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeIndexArray(List *list)
|
makeIndexArray(List *list)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v = makeItemType(jpiIndexArray);
|
JsonPathParseItem *v = makeItemType(jpiIndexArray);
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
Assert(list_length(list) > 0);
|
Assert(list_length(list) > 0);
|
||||||
@ -439,7 +451,7 @@ makeIndexArray(List *list)
|
|||||||
|
|
||||||
foreach(cell, list)
|
foreach(cell, list)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *jpi = lfirst(cell);
|
JsonPathParseItem *jpi = lfirst(cell);
|
||||||
|
|
||||||
Assert(jpi->type == jpiSubscript);
|
Assert(jpi->type == jpiSubscript);
|
||||||
|
|
||||||
@ -453,7 +465,7 @@ makeIndexArray(List *list)
|
|||||||
static JsonPathParseItem *
|
static JsonPathParseItem *
|
||||||
makeAny(int first, int last)
|
makeAny(int first, int last)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v = makeItemType(jpiAny);
|
JsonPathParseItem *v = makeItemType(jpiAny);
|
||||||
|
|
||||||
v->value.anybounds.first = (first >= 0) ? first : PG_UINT32_MAX;
|
v->value.anybounds.first = (first >= 0) ? first : PG_UINT32_MAX;
|
||||||
v->value.anybounds.last = (last >= 0) ? last : PG_UINT32_MAX;
|
v->value.anybounds.last = (last >= 0) ? last : PG_UINT32_MAX;
|
||||||
@ -465,9 +477,9 @@ static JsonPathParseItem *
|
|||||||
makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
|
makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
|
||||||
JsonPathString *flags)
|
JsonPathString *flags)
|
||||||
{
|
{
|
||||||
JsonPathParseItem *v = makeItemType(jpiLikeRegex);
|
JsonPathParseItem *v = makeItemType(jpiLikeRegex);
|
||||||
int i;
|
int i;
|
||||||
int cflags = REG_ADVANCED;
|
int cflags = REG_ADVANCED;
|
||||||
|
|
||||||
v->value.like_regex.expr = expr;
|
v->value.like_regex.expr = expr;
|
||||||
v->value.like_regex.pattern = pattern->val;
|
v->value.like_regex.pattern = pattern->val;
|
||||||
@ -510,4 +522,12 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jsonpath_scan.l is compiled as part of jsonpath_gram.y. Currently, this is
|
||||||
|
* unavoidable because jsonpath_gram does not create a .h file to export its
|
||||||
|
* token symbols. If these files ever grow large enough to be worth compiling
|
||||||
|
* separately, that could be fixed; but for now it seems like useless
|
||||||
|
* complication.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "jsonpath_scan.c"
|
#include "jsonpath_scan.c"
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
* jsonpath_scan.l
|
* jsonpath_scan.l
|
||||||
* Lexical parser for jsonpath datatype
|
* Lexical parser for jsonpath datatype
|
||||||
*
|
*
|
||||||
|
* Splits jsonpath string into tokens represented as JsonPathString structs.
|
||||||
|
* Decodes unicode and hex escaped strings.
|
||||||
|
*
|
||||||
* Copyright (c) 2019, PostgreSQL Global Development Group
|
* Copyright (c) 2019, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
@ -19,9 +22,6 @@
|
|||||||
|
|
||||||
static JsonPathString scanstring;
|
static JsonPathString scanstring;
|
||||||
|
|
||||||
/* No reason to constrain amount of data slurped */
|
|
||||||
/* #define YY_READ_BUF_SIZE 16777216 */
|
|
||||||
|
|
||||||
/* Handles to the buffer that the lexer uses internally */
|
/* Handles to the buffer that the lexer uses internally */
|
||||||
static YY_BUFFER_STATE scanbufhandle;
|
static YY_BUFFER_STATE scanbufhandle;
|
||||||
static char *scanbuf;
|
static char *scanbuf;
|
||||||
@ -29,9 +29,7 @@ static int scanbuflen;
|
|||||||
|
|
||||||
static void addstring(bool init, char *s, int l);
|
static void addstring(bool init, char *s, int l);
|
||||||
static void addchar(bool init, char s);
|
static void addchar(bool init, char s);
|
||||||
static int checkSpecialVal(void); /* examine scanstring for the special
|
static enum yytokentype checkKeyword(void);
|
||||||
* value */
|
|
||||||
|
|
||||||
static void parseUnicode(char *s, int l);
|
static void parseUnicode(char *s, int l);
|
||||||
static void parseHexChars(char *s, int l);
|
static void parseHexChars(char *s, int l);
|
||||||
|
|
||||||
@ -60,11 +58,22 @@ fprintf_to_ereport(const char *fmt, const char *msg)
|
|||||||
%option noyyrealloc
|
%option noyyrealloc
|
||||||
%option noyyfree
|
%option noyyfree
|
||||||
|
|
||||||
%x xQUOTED
|
/*
|
||||||
%x xNONQUOTED
|
* We use exclusive states for quoted, signle-quoted and non-quoted strings,
|
||||||
%x xVARQUOTED
|
* quoted variable names and C-tyle comments.
|
||||||
%x xSINGLEQUOTED
|
* Exclusive states:
|
||||||
%x xCOMMENT
|
* <xq> - quoted strings
|
||||||
|
* <xnq> - non-quoted strings
|
||||||
|
* <xvq> - quoted variable names
|
||||||
|
* <xsq> - single-quoted strings
|
||||||
|
* <xc> - C-style comment
|
||||||
|
*/
|
||||||
|
|
||||||
|
%x xq
|
||||||
|
%x xnq
|
||||||
|
%x xvq
|
||||||
|
%x xsq
|
||||||
|
%x xc
|
||||||
|
|
||||||
special [\?\%\$\.\[\]\{\}\(\)\|\&\!\=\<\>\@\#\,\*:\-\+\/]
|
special [\?\%\$\.\[\]\{\}\(\)\|\&\!\=\<\>\@\#\,\*:\-\+\/]
|
||||||
any [^\?\%\$\.\[\]\{\}\(\)\|\&\!\=\<\>\@\#\,\*:\-\+\/\\\"\' \t\n\r\f]
|
any [^\?\%\$\.\[\]\{\}\(\)\|\&\!\=\<\>\@\#\,\*:\-\+\/\\\"\' \t\n\r\f]
|
||||||
@ -73,189 +82,188 @@ hex_dig [0-9A-Fa-f]
|
|||||||
unicode \\u({hex_dig}{4}|\{{hex_dig}{1,6}\})
|
unicode \\u({hex_dig}{4}|\{{hex_dig}{1,6}\})
|
||||||
hex_char \\x{hex_dig}{2}
|
hex_char \\x{hex_dig}{2}
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
<INITIAL>\&\& { return AND_P; }
|
<xnq>{any}+ {
|
||||||
|
addstring(false, yytext, yyleng);
|
||||||
|
}
|
||||||
|
|
||||||
<INITIAL>\|\| { return OR_P; }
|
<xnq>{blank}+ {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
BEGIN INITIAL;
|
||||||
|
return checkKeyword();
|
||||||
|
}
|
||||||
|
|
||||||
<INITIAL>\! { return NOT_P; }
|
|
||||||
|
|
||||||
<INITIAL>\*\* { return ANY_P; }
|
<xnq>\/\* {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
BEGIN xc;
|
||||||
|
}
|
||||||
|
|
||||||
<INITIAL>\< { return LESS_P; }
|
<xnq>({special}|\"|\') {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
yyless(0);
|
||||||
|
BEGIN INITIAL;
|
||||||
|
return checkKeyword();
|
||||||
|
}
|
||||||
|
|
||||||
<INITIAL>\<\= { return LESSEQUAL_P; }
|
<xnq><<EOF>> {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
BEGIN INITIAL;
|
||||||
|
return checkKeyword();
|
||||||
|
}
|
||||||
|
|
||||||
<INITIAL>\=\= { return EQUAL_P; }
|
<xnq,xq,xvq,xsq>\\[\"\'\\] { addchar(false, yytext[1]); }
|
||||||
|
|
||||||
<INITIAL>\<\> { return NOTEQUAL_P; }
|
<xnq,xq,xvq,xsq>\\b { addchar(false, '\b'); }
|
||||||
|
|
||||||
<INITIAL>\!\= { return NOTEQUAL_P; }
|
<xnq,xq,xvq,xsq>\\f { addchar(false, '\f'); }
|
||||||
|
|
||||||
<INITIAL>\>\= { return GREATEREQUAL_P; }
|
<xnq,xq,xvq,xsq>\\n { addchar(false, '\n'); }
|
||||||
|
|
||||||
<INITIAL>\> { return GREATER_P; }
|
<xnq,xq,xvq,xsq>\\r { addchar(false, '\r'); }
|
||||||
|
|
||||||
<INITIAL>\${any}+ {
|
<xnq,xq,xvq,xsq>\\t { addchar(false, '\t'); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>\\v { addchar(false, '\v'); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>{unicode}+ { parseUnicode(yytext, yyleng); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>{hex_char}+ { parseHexChars(yytext, yyleng); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>\\x { yyerror(NULL, "Hex character sequence is invalid"); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>\\u { yyerror(NULL, "Unicode sequence is invalid"); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>\\. { yyerror(NULL, "Escape sequence is invalid"); }
|
||||||
|
|
||||||
|
<xnq,xq,xvq,xsq>\\ { yyerror(NULL, "Unexpected end after backslash"); }
|
||||||
|
|
||||||
|
<xq,xvq,xsq><<EOF>> { yyerror(NULL, "Unexpected end of quoted string"); }
|
||||||
|
|
||||||
|
<xq>\" {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
BEGIN INITIAL;
|
||||||
|
return STRING_P;
|
||||||
|
}
|
||||||
|
|
||||||
|
<xvq>\" {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
BEGIN INITIAL;
|
||||||
|
return VARIABLE_P;
|
||||||
|
}
|
||||||
|
|
||||||
|
<xsq>\' {
|
||||||
|
yylval->str = scanstring;
|
||||||
|
BEGIN INITIAL;
|
||||||
|
return STRING_P;
|
||||||
|
}
|
||||||
|
|
||||||
|
<xq,xvq>[^\\\"]+ { addstring(false, yytext, yyleng); }
|
||||||
|
|
||||||
|
<xsq>[^\\\']+ { addstring(false, yytext, yyleng); }
|
||||||
|
|
||||||
|
<xc>\*\/ { BEGIN INITIAL; }
|
||||||
|
|
||||||
|
<xc>[^\*]+ { }
|
||||||
|
|
||||||
|
<xc>\* { }
|
||||||
|
|
||||||
|
<xc><<EOF>> { yyerror(NULL, "Unexpected end of comment"); }
|
||||||
|
|
||||||
|
\&\& { return AND_P; }
|
||||||
|
|
||||||
|
\|\| { return OR_P; }
|
||||||
|
|
||||||
|
\! { return NOT_P; }
|
||||||
|
|
||||||
|
\*\* { return ANY_P; }
|
||||||
|
|
||||||
|
\< { return LESS_P; }
|
||||||
|
|
||||||
|
\<\= { return LESSEQUAL_P; }
|
||||||
|
|
||||||
|
\=\= { return EQUAL_P; }
|
||||||
|
|
||||||
|
\<\> { return NOTEQUAL_P; }
|
||||||
|
|
||||||
|
\!\= { return NOTEQUAL_P; }
|
||||||
|
|
||||||
|
\>\= { return GREATEREQUAL_P; }
|
||||||
|
|
||||||
|
\> { return GREATER_P; }
|
||||||
|
|
||||||
|
\${any}+ {
|
||||||
addstring(true, yytext + 1, yyleng - 1);
|
addstring(true, yytext + 1, yyleng - 1);
|
||||||
addchar(false, '\0');
|
addchar(false, '\0');
|
||||||
yylval->str = scanstring;
|
yylval->str = scanstring;
|
||||||
return VARIABLE_P;
|
return VARIABLE_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>\$\" {
|
\$\" {
|
||||||
addchar(true, '\0');
|
addchar(true, '\0');
|
||||||
BEGIN xVARQUOTED;
|
BEGIN xvq;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>{special} { return *yytext; }
|
{special} { return *yytext; }
|
||||||
|
|
||||||
<INITIAL>{blank}+ { /* ignore */ }
|
{blank}+ { /* ignore */ }
|
||||||
|
|
||||||
<INITIAL>\/\* {
|
\/\* {
|
||||||
addchar(true, '\0');
|
addchar(true, '\0');
|
||||||
BEGIN xCOMMENT;
|
BEGIN xc;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>[0-9]+(\.[0-9]+)?[eE][+-]?[0-9]+ /* float */ {
|
[0-9]+(\.[0-9]+)?[eE][+-]?[0-9]+ { /* float */
|
||||||
addstring(true, yytext, yyleng);
|
addstring(true, yytext, yyleng);
|
||||||
addchar(false, '\0');
|
addchar(false, '\0');
|
||||||
yylval->str = scanstring;
|
yylval->str = scanstring;
|
||||||
return NUMERIC_P;
|
return NUMERIC_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>\.[0-9]+[eE][+-]?[0-9]+ /* float */ {
|
\.[0-9]+[eE][+-]?[0-9]+ { /* float */
|
||||||
addstring(true, yytext, yyleng);
|
addstring(true, yytext, yyleng);
|
||||||
addchar(false, '\0');
|
addchar(false, '\0');
|
||||||
yylval->str = scanstring;
|
yylval->str = scanstring;
|
||||||
return NUMERIC_P;
|
return NUMERIC_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>([0-9]+)?\.[0-9]+ {
|
([0-9]+)?\.[0-9]+ {
|
||||||
addstring(true, yytext, yyleng);
|
addstring(true, yytext, yyleng);
|
||||||
addchar(false, '\0');
|
addchar(false, '\0');
|
||||||
yylval->str = scanstring;
|
yylval->str = scanstring;
|
||||||
return NUMERIC_P;
|
return NUMERIC_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>[0-9]+ {
|
[0-9]+ {
|
||||||
addstring(true, yytext, yyleng);
|
addstring(true, yytext, yyleng);
|
||||||
addchar(false, '\0');
|
addchar(false, '\0');
|
||||||
yylval->str = scanstring;
|
yylval->str = scanstring;
|
||||||
return INT_P;
|
return INT_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>{any}+ {
|
{any}+ {
|
||||||
addstring(true, yytext, yyleng);
|
addstring(true, yytext, yyleng);
|
||||||
BEGIN xNONQUOTED;
|
BEGIN xnq;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>\" {
|
\" {
|
||||||
addchar(true, '\0');
|
addchar(true, '\0');
|
||||||
BEGIN xQUOTED;
|
BEGIN xq;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>\' {
|
\' {
|
||||||
addchar(true, '\0');
|
addchar(true, '\0');
|
||||||
BEGIN xSINGLEQUOTED;
|
BEGIN xsq;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>\\ {
|
\\ {
|
||||||
yyless(0);
|
yyless(0);
|
||||||
addchar(true, '\0');
|
addchar(true, '\0');
|
||||||
BEGIN xNONQUOTED;
|
BEGIN xnq;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xNONQUOTED>{any}+ {
|
<<EOF>> { yyterminate(); }
|
||||||
addstring(false, yytext, yyleng);
|
|
||||||
}
|
|
||||||
|
|
||||||
<xNONQUOTED>{blank}+ {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return checkSpecialVal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
<xNONQUOTED>\/\* {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
BEGIN xCOMMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
<xNONQUOTED>({special}|\"|\') {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
yyless(0);
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return checkSpecialVal();
|
|
||||||
}
|
|
||||||
|
|
||||||
<xNONQUOTED><<EOF>> {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return checkSpecialVal();
|
|
||||||
}
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\[\"\'\\] { addchar(false, yytext[1]); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\b { addchar(false, '\b'); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\f { addchar(false, '\f'); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\n { addchar(false, '\n'); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\r { addchar(false, '\r'); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\t { addchar(false, '\t'); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\v { addchar(false, '\v'); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>{unicode}+ { parseUnicode(yytext, yyleng); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>{hex_char}+ { parseHexChars(yytext, yyleng); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\x { yyerror(NULL, "Hex character sequence is invalid"); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\u { yyerror(NULL, "Unicode sequence is invalid"); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\. { yyerror(NULL, "Escape sequence is invalid"); }
|
|
||||||
|
|
||||||
<xNONQUOTED,xQUOTED,xVARQUOTED,xSINGLEQUOTED>\\ { yyerror(NULL, "Unexpected end after backslash"); }
|
|
||||||
|
|
||||||
<xQUOTED,xVARQUOTED,xSINGLEQUOTED><<EOF>> { yyerror(NULL, "Unexpected end of quoted string"); }
|
|
||||||
|
|
||||||
<xQUOTED>\" {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return STRING_P;
|
|
||||||
}
|
|
||||||
|
|
||||||
<xVARQUOTED>\" {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return VARIABLE_P;
|
|
||||||
}
|
|
||||||
|
|
||||||
<xSINGLEQUOTED>\' {
|
|
||||||
yylval->str = scanstring;
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return STRING_P;
|
|
||||||
}
|
|
||||||
|
|
||||||
<xQUOTED,xVARQUOTED>[^\\\"]+ { addstring(false, yytext, yyleng); }
|
|
||||||
|
|
||||||
<xSINGLEQUOTED>[^\\\']+ { addstring(false, yytext, yyleng); }
|
|
||||||
|
|
||||||
<INITIAL><<EOF>> { yyterminate(); }
|
|
||||||
|
|
||||||
<xCOMMENT>\*\/ { BEGIN INITIAL; }
|
|
||||||
|
|
||||||
<xCOMMENT>[^\*]+ { }
|
|
||||||
|
|
||||||
<xCOMMENT>\* { }
|
|
||||||
|
|
||||||
<xCOMMENT><<EOF>> { yyerror(NULL, "Unexpected end of comment"); }
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -292,7 +300,6 @@ typedef struct JsonPathKeyword
|
|||||||
* Array of key words should be sorted by length and then
|
* Array of key words should be sorted by length and then
|
||||||
* alphabetical order
|
* alphabetical order
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const JsonPathKeyword keywords[] = {
|
static const JsonPathKeyword keywords[] = {
|
||||||
{ 2, false, IS_P, "is"},
|
{ 2, false, IS_P, "is"},
|
||||||
{ 2, false, TO_P, "to"},
|
{ 2, false, TO_P, "to"},
|
||||||
@ -317,8 +324,9 @@ static const JsonPathKeyword keywords[] = {
|
|||||||
{ 10,false, LIKE_REGEX_P, "like_regex"},
|
{ 10,false, LIKE_REGEX_P, "like_regex"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
/* Check if current scanstring value is a keyword */
|
||||||
checkSpecialVal()
|
static enum yytokentype
|
||||||
|
checkKeyword()
|
||||||
{
|
{
|
||||||
int res = IDENT_P;
|
int res = IDENT_P;
|
||||||
int diff;
|
int diff;
|
||||||
@ -329,7 +337,7 @@ checkSpecialVal()
|
|||||||
if (scanstring.len > keywords[lengthof(keywords) - 1].len)
|
if (scanstring.len > keywords[lengthof(keywords) - 1].len)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
while(StopLow < StopHigh)
|
while (StopLow < StopHigh)
|
||||||
{
|
{
|
||||||
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
|
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
|
||||||
|
|
||||||
@ -397,49 +405,50 @@ jsonpath_scanner_finish(void)
|
|||||||
pfree(scanbuf);
|
pfree(scanbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resize scanstring so that it can append string of given length.
|
||||||
|
* Reinitialize if required.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
resizeString(bool init, int appendLen)
|
||||||
|
{
|
||||||
|
if (init)
|
||||||
|
{
|
||||||
|
scanstring.total = Max(32, appendLen);
|
||||||
|
scanstring.val = (char *) palloc(scanstring.total);
|
||||||
|
scanstring.len = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (scanstring.len + appendLen >= scanstring.total)
|
||||||
|
{
|
||||||
|
while (scanstring.len + appendLen >= scanstring.total)
|
||||||
|
scanstring.total *= 2;
|
||||||
|
scanstring.val = repalloc(scanstring.val, scanstring.total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add set of bytes at "s" of length "l" to scanstring */
|
||||||
static void
|
static void
|
||||||
addstring(bool init, char *s, int l)
|
addstring(bool init, char *s, int l)
|
||||||
{
|
{
|
||||||
if (init)
|
resizeString(init, l + 1);
|
||||||
{
|
memcpy(scanstring.val + scanstring.len, s, l);
|
||||||
scanstring.total = 32;
|
scanstring.len += l;
|
||||||
scanstring.val = palloc(scanstring.total);
|
|
||||||
scanstring.len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s && l)
|
|
||||||
{
|
|
||||||
while(scanstring.len + l + 1 >= scanstring.total)
|
|
||||||
{
|
|
||||||
scanstring.total *= 2;
|
|
||||||
scanstring.val = repalloc(scanstring.val, scanstring.total);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(scanstring.val + scanstring.len, s, l);
|
|
||||||
scanstring.len += l;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add single byte "c" to scanstring */
|
||||||
static void
|
static void
|
||||||
addchar(bool init, char s)
|
addchar(bool init, char c)
|
||||||
{
|
{
|
||||||
if (init)
|
resizeString(init, 1);
|
||||||
{
|
scanstring.val[scanstring.len] = c;
|
||||||
scanstring.total = 32;
|
if (c != '\0')
|
||||||
scanstring.val = palloc(scanstring.total);
|
|
||||||
scanstring.len = 0;
|
|
||||||
}
|
|
||||||
else if(scanstring.len + 1 >= scanstring.total)
|
|
||||||
{
|
|
||||||
scanstring.total *= 2;
|
|
||||||
scanstring.val = repalloc(scanstring.val, scanstring.total);
|
|
||||||
}
|
|
||||||
|
|
||||||
scanstring.val[ scanstring.len ] = s;
|
|
||||||
if (s != '\0')
|
|
||||||
scanstring.len++;
|
scanstring.len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Interface to jsonpath parser */
|
||||||
JsonPathParseResult *
|
JsonPathParseResult *
|
||||||
parsejsonpath(const char *str, int len)
|
parsejsonpath(const char *str, int len)
|
||||||
{
|
{
|
||||||
@ -447,7 +456,7 @@ parsejsonpath(const char *str, int len)
|
|||||||
|
|
||||||
jsonpath_scanner_init(str, len);
|
jsonpath_scanner_init(str, len);
|
||||||
|
|
||||||
if (jsonpath_yyparse((void*)&parseresult) != 0)
|
if (jsonpath_yyparse((void *) &parseresult) != 0)
|
||||||
jsonpath_yyerror(NULL, "bugus input");
|
jsonpath_yyerror(NULL, "bugus input");
|
||||||
|
|
||||||
jsonpath_scanner_finish();
|
jsonpath_scanner_finish();
|
||||||
@ -455,6 +464,7 @@ parsejsonpath(const char *str, int len)
|
|||||||
return parseresult;
|
return parseresult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Turn hex character into integer */
|
||||||
static int
|
static int
|
||||||
hexval(char c)
|
hexval(char c)
|
||||||
{
|
{
|
||||||
@ -468,6 +478,7 @@ hexval(char c)
|
|||||||
return 0; /* not reached */
|
return 0; /* not reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add given unicode character to scanstring */
|
||||||
static void
|
static void
|
||||||
addUnicodeChar(int ch)
|
addUnicodeChar(int ch)
|
||||||
{
|
{
|
||||||
@ -515,6 +526,7 @@ addUnicodeChar(int ch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add unicode character and process its hi surrogate */
|
||||||
static void
|
static void
|
||||||
addUnicode(int ch, int *hi_surrogate)
|
addUnicode(int ch, int *hi_surrogate)
|
||||||
{
|
{
|
||||||
@ -592,6 +604,7 @@ parseUnicode(char *s, int l)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse sequence of hex-encoded characters */
|
||||||
static void
|
static void
|
||||||
parseHexChars(char *s, int l)
|
parseHexChars(char *s, int l)
|
||||||
{
|
{
|
||||||
@ -601,7 +614,8 @@ parseHexChars(char *s, int l)
|
|||||||
|
|
||||||
for (i = 0; i < l / 4; i++)
|
for (i = 0; i < l / 4; i++)
|
||||||
{
|
{
|
||||||
int ch = (hexval(s[i * 4 + 2]) << 4) | hexval(s[i * 4 + 3]);
|
int ch = (hexval(s[i * 4 + 2]) << 4) |
|
||||||
|
hexval(s[i * 4 + 3]);
|
||||||
|
|
||||||
addUnicodeChar(ch);
|
addUnicodeChar(ch);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user