1
0
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:
Alexander Korotkov 2019-03-25 15:42:51 +03:00
parent d303122eab
commit 8b17298f0b
2 changed files with 233 additions and 199 deletions

View File

@ -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"

View File

@ -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);
} }