}
 
 %{
-static JsonPathString scanstring;
-
-/* Handles to the buffer that the lexer uses internally */
-static YY_BUFFER_STATE scanbufhandle;
-static char *scanbuf;
-static int scanbuflen;
+struct jsonpath_yy_extra_type
+{
+   JsonPathString scanstring;
+};
+#define YY_EXTRA_TYPE struct jsonpath_yy_extra_type *
 
-static void addstring(bool init, char *s, int l);
-static void addchar(bool init, char c);
-static enum yytokentype checkKeyword(void);
-static bool parseUnicode(char *s, int l, struct Node *escontext);
-static bool parseHexChar(char *s, struct Node *escontext);
+static void addstring(bool init, char *s, int l, yyscan_t yyscanner);
+static void addchar(bool init, char c, yyscan_t yyscanner);
+static enum yytokentype checkKeyword(yyscan_t yyscanner);
+static bool parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner);
+static bool parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner);
 
 /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
 #undef fprintf
 %option noyywrap
 %option warn
 %option prefix="jsonpath_yy"
+%option reentrant
 %option bison-bridge
 %option noyyalloc
 %option noyyrealloc
 %%
 
 <xnq>{other}+                  {
-                                   addstring(false, yytext, yyleng);
+                                   addstring(false, yytext, yyleng, yyscanner);
                                }
 
 <xnq>{blank}+                  {
-                                   yylval->str = scanstring;
+                                   yylval->str = yyextra->scanstring;
                                    BEGIN INITIAL;
-                                   return checkKeyword();
+                                   return checkKeyword(yyscanner);
                                }
 
 <xnq>\/\*                      {
-                                   yylval->str = scanstring;
+                                   yylval->str = yyextra->scanstring;
                                    BEGIN xc;
                                }
 
 <xnq>({special}|\")                {
-                                   yylval->str = scanstring;
+                                   yylval->str = yyextra->scanstring;
                                    yyless(0);
                                    BEGIN INITIAL;
-                                   return checkKeyword();
+                                   return checkKeyword(yyscanner);
                                }
 
 <xnq><<EOF>>                   {
-                                   yylval->str = scanstring;
+                                   yylval->str = yyextra->scanstring;
                                    BEGIN INITIAL;
-                                   return checkKeyword();
+                                   return checkKeyword(yyscanner);
                                }
 
-<xnq,xq,xvq>\\b                { addchar(false, '\b'); }
+<xnq,xq,xvq>\\b                { addchar(false, '\b', yyscanner); }
 
-<xnq,xq,xvq>\\f                { addchar(false, '\f'); }
+<xnq,xq,xvq>\\f                { addchar(false, '\f', yyscanner); }
 
-<xnq,xq,xvq>\\n                { addchar(false, '\n'); }
+<xnq,xq,xvq>\\n                { addchar(false, '\n', yyscanner); }
 
-<xnq,xq,xvq>\\r                { addchar(false, '\r'); }
+<xnq,xq,xvq>\\r                { addchar(false, '\r', yyscanner); }
 
-<xnq,xq,xvq>\\t                { addchar(false, '\t'); }
+<xnq,xq,xvq>\\t                { addchar(false, '\t', yyscanner); }
 
-<xnq,xq,xvq>\\v                { addchar(false, '\v'); }
+<xnq,xq,xvq>\\v                { addchar(false, '\v', yyscanner); }
 
 <xnq,xq,xvq>{unicode}+     {
-                               if (!parseUnicode(yytext, yyleng, escontext))
+                               if (!parseUnicode(yytext, yyleng, escontext, yyscanner))
                                    yyterminate();
                            }
 
 <xnq,xq,xvq>{hex_char}     {
-                               if (!parseHexChar(yytext, escontext))
+                               if (!parseHexChar(yytext, escontext, yyscanner))
                                    yyterminate();
                            }
 
 <xnq,xq,xvq>{unicode}*{unicodefail} {
-                               jsonpath_yyerror(NULL, escontext,
+                               jsonpath_yyerror(NULL, escontext, yyscanner,
                                                 "invalid Unicode escape sequence");
                                yyterminate();
                            }
 
 <xnq,xq,xvq>{hex_fail}     {
-                               jsonpath_yyerror(NULL, escontext,
+                               jsonpath_yyerror(NULL, escontext, yyscanner,
                                                 "invalid hexadecimal character sequence");
                                yyterminate();
                            }
 <xnq,xq,xvq>{unicode}+\\   {
                                /* throw back the \\, and treat as unicode */
                                yyless(yyleng - 1);
-                               if (!parseUnicode(yytext, yyleng, escontext))
+                               if (!parseUnicode(yytext, yyleng, escontext, yyscanner))
                                    yyterminate();
                            }
 
-<xnq,xq,xvq>\\.                { addchar(false, yytext[1]); }
+<xnq,xq,xvq>\\.                { addchar(false, yytext[1], yyscanner); }
 
 <xnq,xq,xvq>\\             {
-                               jsonpath_yyerror(NULL, escontext,
+                               jsonpath_yyerror(NULL, escontext, yyscanner,
                                                 "unexpected end after backslash");
                                yyterminate();
                            }
 
 <xq,xvq><<EOF>>                {
-                               jsonpath_yyerror(NULL, escontext,
+                               jsonpath_yyerror(NULL, escontext, yyscanner,
                                                 "unterminated quoted string");
                                yyterminate();
                            }
 
 <xq>\"                         {
-                                   yylval->str = scanstring;
+                                   yylval->str = yyextra->scanstring;
                                    BEGIN INITIAL;
                                    return STRING_P;
                                }
 
 <xvq>\"                            {
-                                   yylval->str = scanstring;
+                                   yylval->str = yyextra->scanstring;
                                    BEGIN INITIAL;
                                    return VARIABLE_P;
                                }
 
-<xq,xvq>[^\\\"]+               { addstring(false, yytext, yyleng); }
+<xq,xvq>[^\\\"]+               { addstring(false, yytext, yyleng, yyscanner); }
 
 <xc>\*\/                       { BEGIN INITIAL; }
 
 <xc>\*                         { }
 
 <xc><<EOF>>                        {
-                                   jsonpath_yyerror(NULL, escontext,
+                                   jsonpath_yyerror(NULL, escontext, yyscanner,
                                                     "unexpected end of comment");
                                    yyterminate();
                                }
 \>                             { return GREATER_P; }
 
 \${other}+                     {
-                                   addstring(true, yytext + 1, yyleng - 1);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext + 1, yyleng - 1, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return VARIABLE_P;
                                }
 
 \$\"                           {
-                                   addchar(true, '\0');
+                                   addchar(true, '\0', yyscanner);
                                    BEGIN xvq;
                                }
 
 {blank}+                       { /* ignore */ }
 
 \/\*                           {
-                                   addchar(true, '\0');
+                                   addchar(true, '\0', yyscanner);
                                    BEGIN xc;
                                }
 
 {real}                         {
-                                   addstring(true, yytext, yyleng);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext, yyleng, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return NUMERIC_P;
                                }
 
 {decimal}                      {
-                                   addstring(true, yytext, yyleng);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext, yyleng, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return NUMERIC_P;
                                }
 
 {decinteger}                   {
-                                   addstring(true, yytext, yyleng);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext, yyleng, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return INT_P;
                                }
 
 {hexinteger}                   {
-                                   addstring(true, yytext, yyleng);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext, yyleng, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return INT_P;
                                }
 
 {octinteger}                   {
-                                   addstring(true, yytext, yyleng);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext, yyleng, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return INT_P;
                                }
 
 {bininteger}                   {
-                                   addstring(true, yytext, yyleng);
-                                   addchar(false, '\0');
-                                   yylval->str = scanstring;
+                                   addstring(true, yytext, yyleng, yyscanner);
+                                   addchar(false, '\0', yyscanner);
+                                   yylval->str = yyextra->scanstring;
                                    return INT_P;
                                }
 
 {realfail}                     {
-                                   jsonpath_yyerror(NULL, escontext,
+                                   jsonpath_yyerror(NULL, escontext, yyscanner,
                                                     "invalid numeric literal");
                                    yyterminate();
                                }
 {decinteger_junk}              {
-                                   jsonpath_yyerror(NULL, escontext,
+                                   jsonpath_yyerror(NULL, escontext, yyscanner,
                                                     "trailing junk after numeric literal");
                                    yyterminate();
                                }
 {decimal_junk}                 {
-                                   jsonpath_yyerror(NULL, escontext,
+                                   jsonpath_yyerror(NULL, escontext, yyscanner,
                                                     "trailing junk after numeric literal");
                                    yyterminate();
                                }
 {real_junk}                        {
-                                   jsonpath_yyerror(NULL, escontext,
+                                   jsonpath_yyerror(NULL, escontext, yyscanner,
                                                     "trailing junk after numeric literal");
                                    yyterminate();
                                }
 \"                             {
-                                   addchar(true, '\0');
+                                   addchar(true, '\0', yyscanner);
                                    BEGIN xq;
                                }
 
 \\                             {
                                    yyless(0);
-                                   addchar(true, '\0');
+                                   addchar(true, '\0', yyscanner);
                                    BEGIN xnq;
                                }
 
 {other}+                       {
-                                   addstring(true, yytext, yyleng);
+                                   addstring(true, yytext, yyleng, yyscanner);
                                    BEGIN xnq;
                                }
 
 
 /* LCOV_EXCL_STOP */
 
+/* see scan.l */
+#undef yyextra
+#define yyextra  (((struct yyguts_t *) yyscanner)->yyextra_r)
+
 void
 jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext,
+                yyscan_t yyscanner,
                 const char *message)
 {
+   struct yyguts_t * yyg = (struct yyguts_t *) yyscanner;  /* needed for yytext macro */
+
    /* don't overwrite escontext if it's already been set */
    if (SOFT_ERROR_OCCURRED(escontext))
        return;
    { 12,false, TIMESTAMP_TZ_P, "timestamp_tz"},
 };
 
-/* Check if current scanstring value is a keyword */
+/*
+ * Check if current scanstring value is a keyword
+ */
 static enum yytokentype
-checkKeyword()
+checkKeyword(yyscan_t yyscanner)
 {
    int         res = IDENT_P;
    int         diff;
                           *StopHigh = keywords + lengthof(keywords),
                           *StopMiddle;
 
-   if (scanstring.len > keywords[lengthof(keywords) - 1].len)
+   if (yyextra->scanstring.len > keywords[lengthof(keywords) - 1].len)
        return res;
 
    while (StopLow < StopHigh)
    {
        StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
 
-       if (StopMiddle->len == scanstring.len)
-           diff = pg_strncasecmp(StopMiddle->keyword, scanstring.val,
-                                 scanstring.len);
+       if (StopMiddle->len == yyextra->scanstring.len)
+           diff = pg_strncasecmp(StopMiddle->keyword, yyextra->scanstring.val,
+                                 yyextra->scanstring.len);
        else
-           diff = StopMiddle->len - scanstring.len;
+           diff = StopMiddle->len - yyextra->scanstring.len;
 
        if (diff < 0)
            StopLow = StopMiddle + 1;
        else
        {
            if (StopMiddle->lowercase)
-               diff = strncmp(StopMiddle->keyword, scanstring.val,
-                              scanstring.len);
+               diff = strncmp(StopMiddle->keyword, yyextra->scanstring.val,
+                              yyextra->scanstring.len);
 
            if (diff == 0)
                res = StopMiddle->val;
    return res;
 }
 
-/*
- * Called before any actual parsing is done
- */
-static void
-jsonpath_scanner_init(const char *str, int slen)
-{
-   if (slen <= 0)
-       slen = strlen(str);
-
-   /*
-    * Might be left over after ereport()
-    */
-   yy_init_globals();
-
-   /*
-    * Make a scan buffer with special termination needed by flex.
-    */
-
-   scanbuflen = slen;
-   scanbuf = palloc(slen + 2);
-   memcpy(scanbuf, str, slen);
-   scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
-   scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
-
-   BEGIN(INITIAL);
-}
-
-
-/*
- * Called after parsing is done to clean up after jsonpath_scanner_init()
- */
-static void
-jsonpath_scanner_finish(void)
-{
-   yy_delete_buffer(scanbufhandle);
-   pfree(scanbuf);
-}
-
 /*
  * Resize scanstring so that it can append string of given length.
  * Reinitialize if required.
  */
 static void
-resizeString(bool init, int appendLen)
+resizeString(bool init, int appendLen, yyscan_t yyscanner)
 {
    if (init)
    {
-       scanstring.total = Max(32, appendLen);
-       scanstring.val = (char *) palloc(scanstring.total);
-       scanstring.len = 0;
+       yyextra->scanstring.total = Max(32, appendLen);
+       yyextra->scanstring.val = (char *) palloc(yyextra->scanstring.total);
+       yyextra->scanstring.len = 0;
    }
    else
    {
-       if (scanstring.len + appendLen >= scanstring.total)
+       if (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total)
        {
-           while (scanstring.len + appendLen >= scanstring.total)
-               scanstring.total *= 2;
-           scanstring.val = repalloc(scanstring.val, scanstring.total);
+           while (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total)
+               yyextra->scanstring.total *= 2;
+           yyextra->scanstring.val = repalloc(yyextra->scanstring.val, yyextra->scanstring.total);
        }
    }
 }
 
 /* Add set of bytes at "s" of length "l" to scanstring */
 static void
-addstring(bool init, char *s, int l)
+addstring(bool init, char *s, int l, yyscan_t yyscanner)
 {
-   resizeString(init, l + 1);
-   memcpy(scanstring.val + scanstring.len, s, l);
-   scanstring.len += l;
+   resizeString(init, l + 1, yyscanner);
+   memcpy(yyextra->scanstring.val + yyextra->scanstring.len, s, l);
+   yyextra->scanstring.len += l;
 }
 
 /* Add single byte "c" to scanstring */
 static void
-addchar(bool init, char c)
+addchar(bool init, char c, yyscan_t yyscanner)
 {
-   resizeString(init, 1);
-   scanstring.val[scanstring.len] = c;
+   resizeString(init, 1, yyscanner);
+   yyextra->scanstring.val[yyextra->scanstring.len] = c;
    if (c != '\0')
-       scanstring.len++;
+       yyextra->scanstring.len++;
 }
 
 /* Interface to jsonpath parser */
 parsejsonpath(const char *str, int len, struct Node *escontext)
 {
    JsonPathParseResult *parseresult;
+   yyscan_t    scanner;
+   struct jsonpath_yy_extra_type yyext;
+
+   if (jsonpath_yylex_init(&scanner) != 0)
+       elog(ERROR, "yylex_init() failed: %m");
+
+   yyset_extra(&yyext, scanner);
+
+   if (len <= 0)
+       len = strlen(str);
 
-   jsonpath_scanner_init(str, len);
+   jsonpath_yy_scan_bytes(str, len, scanner);
 
-   if (jsonpath_yyparse(&parseresult, escontext) != 0)
-       jsonpath_yyerror(NULL, escontext, "invalid input"); /* shouldn't happen */
+   if (jsonpath_yyparse(&parseresult, escontext, scanner) != 0)
+       jsonpath_yyerror(NULL, escontext, scanner, "invalid input"); /* shouldn't happen */
 
-   jsonpath_scanner_finish();
+   jsonpath_yylex_destroy(scanner);
 
    return parseresult;
 }
 
 /* Turn hex character into integer */
 static bool
-hexval(char c, int *result, struct Node *escontext)
+hexval(char c, int *result, struct Node *escontext, yyscan_t yyscanner)
 {
    if (c >= '0' && c <= '9')
    {
        *result = c - 'A' + 0xA;
        return true;
    }
-   jsonpath_yyerror(NULL, escontext, "invalid hexadecimal digit");
+   jsonpath_yyerror(NULL, escontext, yyscanner, "invalid hexadecimal digit");
    return false;
 }
 
 /* Add given unicode character to scanstring */
 static bool
-addUnicodeChar(int ch, struct Node *escontext)
+addUnicodeChar(int ch, struct Node *escontext, yyscan_t yyscanner)
 {
    if (ch == 0)
    {
            ereturn(escontext, false,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("could not convert Unicode to server encoding")));
-       addstring(false, cbuf, strlen(cbuf));
+       addstring(false, cbuf, strlen(cbuf), yyscanner);
    }
    return true;
 }
 
 /* Add unicode character, processing any surrogate pairs */
 static bool
-addUnicode(int ch, int *hi_surrogate, struct Node *escontext)
+addUnicode(int ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner)
 {
    if (is_utf16_surrogate_first(ch))
    {
                           "surrogate.")));
    }
 
-   return addUnicodeChar(ch, escontext);
+   return addUnicodeChar(ch, escontext, yyscanner);
 }
 
 /*
  * src/backend/utils/adt/json.c
  */
 static bool
-parseUnicode(char *s, int l, struct Node *escontext)
+parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner)
 {
    int         i = 2;
    int         hi_surrogate = -1;
        {
            while (s[++i] != '}' && i < l)
            {
-               if (!hexval(s[i], &si, escontext))
+               if (!hexval(s[i], &si, escontext, yyscanner))
                    return false;
                ch = (ch << 4) | si;
            }
        {
            for (j = 0; j < 4 && i < l; j++)
            {
-               if (!hexval(s[i++], &si, escontext))
+               if (!hexval(s[i++], &si, escontext, yyscanner))
                    return false;
                ch = (ch << 4) | si;
            }
        }
 
-       if (! addUnicode(ch, &hi_surrogate, escontext))
+       if (! addUnicode(ch, &hi_surrogate, escontext, yyscanner))
            return false;
    }
 
 
 /* Parse sequence of hex-encoded characters */
 static bool
-parseHexChar(char *s, struct Node *escontext)
+parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner)
 {
    int s2, s3, ch;
-   if (!hexval(s[2], &s2, escontext))
+   if (!hexval(s[2], &s2, escontext, yyscanner))
        return false;
-   if (!hexval(s[3], &s3, escontext))
+   if (!hexval(s[3], &s3, escontext, yyscanner))
        return false;
 
    ch = (s2 << 4) | s3;
 
-   return addUnicodeChar(ch, escontext);
+   return addUnicodeChar(ch, escontext, yyscanner);
 }
 
 /*
  */
 
 void *
-jsonpath_yyalloc(yy_size_t bytes)
+jsonpath_yyalloc(yy_size_t bytes, yyscan_t yyscanner)
 {
    return palloc(bytes);
 }
 
 void *
-jsonpath_yyrealloc(void *ptr, yy_size_t bytes)
+jsonpath_yyrealloc(void *ptr, yy_size_t bytes, yyscan_t yyscanner)
 {
    if (ptr)
        return repalloc(ptr, bytes);
 }
 
 void
-jsonpath_yyfree(void *ptr)
+jsonpath_yyfree(void *ptr, yyscan_t yyscanner)
 {
    if (ptr)
        pfree(ptr);