[09/13] Move lexptr and prev_lexptr to parser_state

Message ID 20190403013805.11978-10-tom@tromey.com
State New
Headers show
Series
  • Remove parser-related globals
Related show

Commit Message

Tom Tromey April 3, 2019, 1:38 a.m.
This removes the lexptr and prev_lexptr globals, in favor of members
of parser_state.  prev_lexptr could be isolated to each parser, but
since every parser uses it, that did not seem necessary.

2019-04-02  Tom Tromey  <tom@tromey.com>

	* rust-exp.y (struct rust_parser) <lex_hex, lex_escape,
	lex_operator, push_back>: New methods.
	Update all rules.
	(rust_parser::lex_hex, lex_escape): Rename and update.
	(rust_parser::lex_string, rust_parser::lex_identifier): Update.
	(rust_parser::lex_operator): Rename and update.
	(rust_parser::lex_number, rustyylex, rustyyerror)
	(rust_lex_test_init, rust_lex_test_sequence)
	(rust_lex_test_push_back, rust_lex_tests): Update.
	* parser-defs.h (struct parser_state) <parser_state>: Add "input"
	parameter.
	<lexptr, prev_lexptr>: New members.
	(lexptr, prev_lexptr): Don't declare.
	* parse.c (lexptr, prev_lexptr): Remove globals.
	(parse_exp_in_context): Update.
	* p-exp.y (yylex, yyerror): Update.
	* m2-exp.y (parse_number, yylex, yyerror): Update.
	* go-exp.y (lex_one_token, yyerror): Update.
	* f-exp.y (match_string_literal, yylex, yyerror): Update.
	* d-exp.y (lex_one_token, yyerror): Update.
	* c-exp.y (scan_macro_expansion, finished_macro_expansion)
	(lex_one_token, yyerror): Update.
	* ada-lex.l (YY_INPUT): Update.
	(rewind_to_char): Update.
	* ada-exp.y (yyerror): Update.
---
 gdb/ChangeLog     |  28 ++++++
 gdb/ada-exp.y     |   2 +-
 gdb/ada-lex.l     |  12 +--
 gdb/c-exp.y       |  50 +++++-----
 gdb/d-exp.y       |  40 ++++----
 gdb/f-exp.y       |  42 ++++----
 gdb/go-exp.y      |  40 ++++----
 gdb/m2-exp.y      |  40 ++++----
 gdb/p-exp.y       |  50 +++++-----
 gdb/parse.c       |  11 +-
 gdb/parser-defs.h |  24 +++--
 gdb/rust-exp.y    | 248 ++++++++++++++++++++++++----------------------
 12 files changed, 312 insertions(+), 275 deletions(-)

-- 
2.17.2

Patch

diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 0cf85c52dd0..f50500c2e7f 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -745,7 +745,7 @@  ada_parse (struct parser_state *par_state)
 static void
 yyerror (const char *msg)
 {
-  error (_("Error in expression, near `%s'."), lexptr);
+  error (_("Error in expression, near `%s'."), pstate->lexptr);
 }
 
 /* Emit expression to access an instance of SYM, in block BLOCK (if
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 43bd25c1e2f..f7fac27410e 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -73,13 +73,13 @@  static void rewind_to_char (int);
 
 #undef YY_INPUT
 #define YY_INPUT(BUF, RESULT, MAX_SIZE) \
-    if ( *lexptr == '\000' ) \
+    if ( *pstate->lexptr == '\000' ) \
       (RESULT) = YY_NULL; \
     else \
       { \
-        *(BUF) = *lexptr; \
+        *(BUF) = *pstate->lexptr; \
         (RESULT) = 1; \
-	lexptr += 1; \
+	pstate->lexptr += 1; \
       }
 
 static int find_dot_all (const char *);
@@ -628,9 +628,9 @@  processAttribute (const char *str)
 static void
 rewind_to_char (int ch)
 {
-  lexptr -= yyleng;
-  while (toupper (*lexptr) != toupper (ch))
-    lexptr -= 1;
+  pstate->lexptr -= yyleng;
+  while (toupper (*pstate->lexptr) != toupper (ch))
+    pstate->lexptr -= 1;
   yyrestart (NULL);
 }
 
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 16b291f9c70..c85bb3133e8 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -2483,8 +2483,8 @@  scan_macro_expansion (char *expansion)
 
   /* Save the old lexptr value, so we can return to it when we're done
      parsing the expanded text.  */
-  cpstate->macro_original_text = lexptr;
-  lexptr = copy;
+  cpstate->macro_original_text = pstate->lexptr;
+  pstate->lexptr = copy;
 }
 
 static int
@@ -2500,7 +2500,7 @@  finished_macro_expansion (void)
   gdb_assert (cpstate->macro_original_text);
 
   /* Pop back to the original text.  */
-  lexptr = cpstate->macro_original_text;
+  pstate->lexptr = cpstate->macro_original_text;
   cpstate->macro_original_text = 0;
 }
 
@@ -2550,7 +2550,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
   /* Check if this is a macro invocation that we need to expand.  */
   if (! scanning_macro_expansion ())
     {
-      char *expanded = macro_expand_next (&lexptr,
+      char *expanded = macro_expand_next (&pstate->lexptr,
                                           standard_macro_lookup,
                                           expression_macro_scope);
 
@@ -2558,9 +2558,9 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
         scan_macro_expansion (expanded);
     }
 
-  prev_lexptr = lexptr;
+  pstate->prev_lexptr = pstate->lexptr;
 
-  tokstart = lexptr;
+  tokstart = pstate->lexptr;
   /* See if it is a special token of length 3.  */
   for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
     if (strncmp (tokstart, tokentab3[i].oper, 3) == 0)
@@ -2569,7 +2569,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	    && par_state->language ()->la_language != language_cplus)
 	  break;
 
-	lexptr += 3;
+	pstate->lexptr += 3;
 	yylval.opcode = tokentab3[i].opcode;
 	return tokentab3[i].token;
       }
@@ -2582,7 +2582,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	    && par_state->language ()->la_language != language_cplus)
 	  break;
 
-	lexptr += 2;
+	pstate->lexptr += 2;
 	yylval.opcode = tokentab2[i].opcode;
 	if (tokentab2[i].token == ARROW)
 	  last_was_structop = 1;
@@ -2616,13 +2616,13 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      pstate->lexptr++;
       goto retry;
 
     case '[':
     case '(':
       paren_depth++;
-      lexptr++;
+      pstate->lexptr++;
       if (par_state->language ()->la_language == language_objc
 	  && c == '[')
 	return OBJC_LBRAC;
@@ -2633,7 +2633,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
       if (paren_depth == 0)
 	return 0;
       paren_depth--;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ',':
@@ -2641,12 +2641,12 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
           && paren_depth == 0
           && ! scanning_macro_expansion ())
 	return 0;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '.':
       /* Might be a floating point number.  */
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (pstate->lexptr[1] < '0' || pstate->lexptr[1] > '9')
 	{
 	  last_was_structop = true;
 	  goto symbol;		/* Nope, must be a symbol. */
@@ -2713,7 +2713,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	    err_copy[p - tokstart] = 0;
 	    error (_("Invalid number \"%s\"."), err_copy);
 	  }
-	lexptr = p;
+	pstate->lexptr = p;
 	return toktype;
       }
 
@@ -2728,7 +2728,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	    if (strncmp (p, "selector", len) == 0
 		&& (p[len] == '\0' || ISSPACE (p[len])))
 	      {
-		lexptr = p + len;
+		pstate->lexptr = p + len;
 		return SELECTOR;
 	      }
 	    else if (*p == '"')
@@ -2741,7 +2741,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	if (strncmp (p, "entry", len) == 0 && !c_ident_is_alnum (p[len])
 	    && p[len] != '_')
 	  {
-	    lexptr = &p[len];
+	    pstate->lexptr = &p[len];
 	    return ENTRY;
 	  }
       }
@@ -2764,7 +2764,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
     case '{':
     case '}':
     symbol:
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case 'L':
@@ -2779,8 +2779,8 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
     parse_string:
       {
 	int host_len;
-	int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval,
-					   &host_len);
+	int result = parse_string_or_char (tokstart, &pstate->lexptr,
+					   &yylval.tsval, &host_len);
 	if (result == CHAR)
 	  {
 	    if (host_len == 0)
@@ -2788,7 +2788,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	    else if (host_len > 2 && c == '\'')
 	      {
 		++tokstart;
-		namelen = lexptr - tokstart - 1;
+		namelen = pstate->lexptr - tokstart - 1;
 		*is_quoted_name = true;
 
 		goto tryname;
@@ -2860,7 +2860,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	return 0;
     }
 
-  lexptr += namelen;
+  pstate->lexptr += namelen;
 
   tryname:
 
@@ -2902,7 +2902,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
   if (*tokstart == '$')
     return DOLLAR_VARIABLE;
 
-  if (parse_completion && *lexptr == '\0')
+  if (parse_completion && *pstate->lexptr == '\0')
     saw_name_at_eof = 1;
 
   yylval.ssym.stoken = yylval.sval;
@@ -3388,8 +3388,8 @@  c_print_token (FILE *file, int type, YYSTYPE value)
 static void
 yyerror (const char *msg)
 {
-  if (prev_lexptr)
-    lexptr = prev_lexptr;
+  if (pstate->prev_lexptr)
+    pstate->lexptr = pstate->prev_lexptr;
 
-  error (_("A %s in expression, near `%s'."), msg, lexptr);
+  error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
 }
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index 06e12e32011..9addf6c0410 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -1039,14 +1039,14 @@  lex_one_token (struct parser_state *par_state)
 
  retry:
 
-  prev_lexptr = lexptr;
+  pstate->prev_lexptr = pstate->lexptr;
 
-  tokstart = lexptr;
+  tokstart = pstate->lexptr;
   /* See if it is a special token of length 3.  */
   for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
     if (strncmp (tokstart, tokentab3[i].oper, 3) == 0)
       {
-	lexptr += 3;
+	pstate->lexptr += 3;
 	yylval.opcode = tokentab3[i].opcode;
 	return tokentab3[i].token;
       }
@@ -1055,7 +1055,7 @@  lex_one_token (struct parser_state *par_state)
   for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
     if (strncmp (tokstart, tokentab2[i].oper, 2) == 0)
       {
-	lexptr += 2;
+	pstate->lexptr += 2;
 	yylval.opcode = tokentab2[i].opcode;
 	return tokentab2[i].token;
       }
@@ -1080,13 +1080,13 @@  lex_one_token (struct parser_state *par_state)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      pstate->lexptr++;
       goto retry;
 
     case '[':
     case '(':
       paren_depth++;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ']':
@@ -1094,18 +1094,18 @@  lex_one_token (struct parser_state *par_state)
       if (paren_depth == 0)
 	return 0;
       paren_depth--;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ',':
       if (pstate->comma_terminates && paren_depth == 0)
 	return 0;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '.':
       /* Might be a floating point number.  */
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (pstate->lexptr[1] < '0' || pstate->lexptr[1] > '9')
 	{
 	  if (parse_completion)
 	    last_was_structop = 1;
@@ -1170,7 +1170,7 @@  lex_one_token (struct parser_state *par_state)
 	    err_copy[p - tokstart] = 0;
 	    error (_("Invalid number \"%s\"."), err_copy);
 	  }
-	lexptr = p;
+	pstate->lexptr = p;
 	return toktype;
       }
 
@@ -1184,7 +1184,7 @@  lex_one_token (struct parser_state *par_state)
 	if (strncmp (p, "entry", len) == 0 && !isalnum (p[len])
 	    && p[len] != '_')
 	  {
-	    lexptr = &p[len];
+	    pstate->lexptr = &p[len];
 	    return ENTRY;
 	  }
       }
@@ -1207,7 +1207,7 @@  lex_one_token (struct parser_state *par_state)
     case '{':
     case '}':
     symbol:
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '\'':
@@ -1215,8 +1215,8 @@  lex_one_token (struct parser_state *par_state)
     case '`':
       {
 	int host_len;
-	int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval,
-					   &host_len);
+	int result = parse_string_or_char (tokstart, &pstate->lexptr,
+					   &yylval.tsval, &host_len);
 	if (result == CHARACTER_LITERAL)
 	  {
 	    if (host_len == 0)
@@ -1224,7 +1224,7 @@  lex_one_token (struct parser_state *par_state)
 	    else if (host_len > 2 && c == '\'')
 	      {
 		++tokstart;
-		namelen = lexptr - tokstart - 1;
+		namelen = pstate->lexptr - tokstart - 1;
 		goto tryname;
 	      }
 	    else if (host_len > 1)
@@ -1269,7 +1269,7 @@  lex_one_token (struct parser_state *par_state)
         return 0;
     }
 
-  lexptr += namelen;
+  pstate->lexptr += namelen;
 
  tryname:
 
@@ -1308,7 +1308,7 @@  lex_one_token (struct parser_state *par_state)
 	return NAME_OR_INT;
     }
 
-  if (parse_completion && *lexptr == '\0')
+  if (parse_completion && *pstate->lexptr == '\0')
     saw_name_at_eof = 1;
 
   return IDENTIFIER;
@@ -1634,9 +1634,9 @@  d_parse (struct parser_state *par_state)
 static void
 yyerror (const char *msg)
 {
-  if (prev_lexptr)
-    lexptr = prev_lexptr;
+  if (pstate->prev_lexptr)
+    pstate->lexptr = pstate->prev_lexptr;
 
-  error (_("A %s in expression, near `%s'."), msg, lexptr);
+  error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
 }
 
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 522751d2263..fce90b48ef5 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -1005,14 +1005,14 @@  growbuf_by_size (int count)
 static int
 match_string_literal (void)
 {
-  const char *tokptr = lexptr;
+  const char *tokptr = pstate->lexptr;
 
   for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
     {
       CHECKBUF (1);
-      if (*tokptr == *lexptr)
+      if (*tokptr == *pstate->lexptr)
 	{
-	  if (*(tokptr + 1) == *lexptr)
+	  if (*(tokptr + 1) == *pstate->lexptr)
 	    tokptr++;
 	  else
 	    break;
@@ -1027,7 +1027,7 @@  match_string_literal (void)
       tempbuf[tempbufindex] = '\0';
       yylval.sval.ptr = tempbuf;
       yylval.sval.length = tempbufindex;
-      lexptr = ++tokptr;
+      pstate->lexptr = ++tokptr;
       return STRING_LITERAL;
     }
 }
@@ -1044,21 +1044,21 @@  yylex (void)
   
  retry:
  
-  prev_lexptr = lexptr;
+  pstate->prev_lexptr = pstate->lexptr;
  
-  tokstart = lexptr;
+  tokstart = pstate->lexptr;
 
   /* First of all, let us make sure we are not dealing with the
      special tokens .true. and .false. which evaluate to 1 and 0.  */
 
-  if (*lexptr == '.')
+  if (*pstate->lexptr == '.')
     {
       for (int i = 0; i < ARRAY_SIZE (boolean_values); i++)
 	{
 	  if (strncasecmp (tokstart, boolean_values[i].name,
 			   strlen (boolean_values[i].name)) == 0)
 	    {
-	      lexptr += strlen (boolean_values[i].name);
+	      pstate->lexptr += strlen (boolean_values[i].name);
 	      yylval.lval = boolean_values[i].value;
 	      return BOOLEAN_LITERAL;
 	    }
@@ -1071,7 +1071,7 @@  yylex (void)
 		     strlen (dot_ops[i].oper)) == 0)
       {
 	gdb_assert (!dot_ops[i].case_sensitive);
-	lexptr += strlen (dot_ops[i].oper);
+	pstate->lexptr += strlen (dot_ops[i].oper);
 	yylval.opcode = dot_ops[i].opcode;
 	return dot_ops[i].token;
       }
@@ -1080,7 +1080,7 @@  yylex (void)
 
   if (strncmp (tokstart, "**", 2) == 0)
     {
-      lexptr += 2;
+      pstate->lexptr += 2;
       yylval.opcode = BINOP_EXP;
       return STARSTAR;
     }
@@ -1093,7 +1093,7 @@  yylex (void)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      pstate->lexptr++;
       goto retry;
       
     case '\'':
@@ -1104,25 +1104,25 @@  yylex (void)
       
     case '(':
       paren_depth++;
-      lexptr++;
+      pstate->lexptr++;
       return c;
       
     case ')':
       if (paren_depth == 0)
 	return 0;
       paren_depth--;
-      lexptr++;
+      pstate->lexptr++;
       return c;
       
     case ',':
       if (pstate->comma_terminates && paren_depth == 0)
 	return 0;
-      lexptr++;
+      pstate->lexptr++;
       return c;
       
     case '.':
       /* Might be a floating point number.  */
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (pstate->lexptr[1] < '0' || pstate->lexptr[1] > '9')
 	goto symbol;		/* Nope, must be a symbol.  */
       /* FALL THRU.  */
       
@@ -1186,7 +1186,7 @@  yylex (void)
 	    err_copy[p - tokstart] = 0;
 	    error (_("Invalid number \"%s\"."), err_copy);
 	  }
-	lexptr = p;
+	pstate->lexptr = p;
 	return toktype;
       }
       
@@ -1211,7 +1211,7 @@  yylex (void)
     case '{':
     case '}':
     symbol:
-      lexptr++;
+      pstate->lexptr++;
       return c;
     }
   
@@ -1232,7 +1232,7 @@  yylex (void)
   if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
     return 0;
   
-  lexptr += namelen;
+  pstate->lexptr += namelen;
   
   /* Catch specific keywords.  */
 
@@ -1339,8 +1339,8 @@  f_parse (struct parser_state *par_state)
 static void
 yyerror (const char *msg)
 {
-  if (prev_lexptr)
-    lexptr = prev_lexptr;
+  if (pstate->prev_lexptr)
+    pstate->lexptr = pstate->prev_lexptr;
 
-  error (_("A %s in expression, near `%s'."), msg, lexptr);
+  error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
 }
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index ea1487cb008..6754d5217e5 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -1020,14 +1020,14 @@  lex_one_token (struct parser_state *par_state)
 
  retry:
 
-  prev_lexptr = lexptr;
+  par_state->prev_lexptr = par_state->lexptr;
 
-  tokstart = lexptr;
+  tokstart = par_state->lexptr;
   /* See if it is a special token of length 3.  */
   for (i = 0; i < sizeof (tokentab3) / sizeof (tokentab3[0]); i++)
     if (strncmp (tokstart, tokentab3[i].oper, 3) == 0)
       {
-	lexptr += 3;
+	par_state->lexptr += 3;
 	yylval.opcode = tokentab3[i].opcode;
 	return tokentab3[i].token;
       }
@@ -1036,7 +1036,7 @@  lex_one_token (struct parser_state *par_state)
   for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
     if (strncmp (tokstart, tokentab2[i].oper, 2) == 0)
       {
-	lexptr += 2;
+	par_state->lexptr += 2;
 	yylval.opcode = tokentab2[i].opcode;
 	/* NOTE: -> doesn't exist in Go, so we don't need to watch for
 	   setting last_was_structop here.  */
@@ -1059,13 +1059,13 @@  lex_one_token (struct parser_state *par_state)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      par_state->lexptr++;
       goto retry;
 
     case '[':
     case '(':
       paren_depth++;
-      lexptr++;
+      par_state->lexptr++;
       return c;
 
     case ']':
@@ -1073,19 +1073,19 @@  lex_one_token (struct parser_state *par_state)
       if (paren_depth == 0)
 	return 0;
       paren_depth--;
-      lexptr++;
+      par_state->lexptr++;
       return c;
 
     case ',':
       if (pstate->comma_terminates
           && paren_depth == 0)
 	return 0;
-      lexptr++;
+      par_state->lexptr++;
       return c;
 
     case '.':
       /* Might be a floating point number.  */
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (par_state->lexptr[1] < '0' || par_state->lexptr[1] > '9')
 	{
 	  if (parse_completion)
 	    last_was_structop = 1;
@@ -1148,7 +1148,7 @@  lex_one_token (struct parser_state *par_state)
 	    err_copy[p - tokstart] = 0;
 	    error (_("Invalid number \"%s\"."), err_copy);
 	  }
-	lexptr = p;
+	par_state->lexptr = p;
 	return toktype;
       }
 
@@ -1162,7 +1162,7 @@  lex_one_token (struct parser_state *par_state)
 	if (strncmp (p, "entry", len) == 0 && !isalnum (p[len])
 	    && p[len] != '_')
 	  {
-	    lexptr = &p[len];
+	    par_state->lexptr = &p[len];
 	    return ENTRY;
 	  }
       }
@@ -1185,7 +1185,7 @@  lex_one_token (struct parser_state *par_state)
     case '{':
     case '}':
     symbol:
-      lexptr++;
+      par_state->lexptr++;
       return c;
 
     case '\'':
@@ -1193,8 +1193,8 @@  lex_one_token (struct parser_state *par_state)
     case '`':
       {
 	int host_len;
-	int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval,
-					   &host_len);
+	int result = parse_string_or_char (tokstart, &par_state->lexptr,
+					   &yylval.tsval, &host_len);
 	if (result == CHAR)
 	  {
 	    if (host_len == 0)
@@ -1202,7 +1202,7 @@  lex_one_token (struct parser_state *par_state)
 	    else if (host_len > 2 && c == '\'')
 	      {
 		++tokstart;
-		namelen = lexptr - tokstart - 1;
+		namelen = par_state->lexptr - tokstart - 1;
 		goto tryname;
 	      }
 	    else if (host_len > 1)
@@ -1255,7 +1255,7 @@  lex_one_token (struct parser_state *par_state)
 	return 0;
     }
 
-  lexptr += namelen;
+  par_state->lexptr += namelen;
 
   tryname:
 
@@ -1276,7 +1276,7 @@  lex_one_token (struct parser_state *par_state)
   if (*tokstart == '$')
     return DOLLAR_VARIABLE;
 
-  if (parse_completion && *lexptr == '\0')
+  if (parse_completion && *par_state->lexptr == '\0')
     saw_name_at_eof = 1;
   return NAME;
 }
@@ -1581,8 +1581,8 @@  go_parse (struct parser_state *par_state)
 static void
 yyerror (const char *msg)
 {
-  if (prev_lexptr)
-    lexptr = prev_lexptr;
+  if (pstate->prev_lexptr)
+    pstate->lexptr = pstate->prev_lexptr;
 
-  error (_("A %s in expression, near `%s'."), msg, lexptr);
+  error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
 }
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index 2174014e79a..6ba8eaf8554 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -618,7 +618,7 @@  type
 static int
 parse_number (int olen)
 {
-  const char *p = lexptr;
+  const char *p = pstate->lexptr;
   LONGEST n = 0;
   LONGEST prevn = 0;
   int c,i,ischar=0;
@@ -649,7 +649,7 @@  parse_number (int olen)
 			  yylval.val))
 	  return ERROR;
 
-	lexptr += len;
+	pstate->lexptr += len;
 	return FLOAT;
       }
     if (p[c] == '.' && base != 10)
@@ -689,9 +689,9 @@  parse_number (int olen)
 	 prevn=n;
     }
 
-  lexptr = p;
+  pstate->lexptr = p;
   if(*p == 'B' || *p == 'C' || *p == 'H')
-     lexptr++;			/* Advance past B,C or H */
+     pstate->lexptr++;			/* Advance past B,C or H */
 
   if (ischar)
   {
@@ -782,16 +782,16 @@  yylex (void)
 
  retry:
 
-  prev_lexptr = lexptr;
+  pstate->prev_lexptr = pstate->lexptr;
 
-  tokstart = lexptr;
+  tokstart = pstate->lexptr;
 
 
   /* See if it is a special token of length 2 */
   for( i = 0 ; i < (int) (sizeof tokentab2 / sizeof tokentab2[0]) ; i++)
      if (strncmp (tokentab2[i].name, tokstart, 2) == 0)
      {
-	lexptr += 2;
+	pstate->lexptr += 2;
 	return tokentab2[i].token;
      }
 
@@ -803,34 +803,34 @@  yylex (void)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      pstate->lexptr++;
       goto retry;
 
     case '(':
       paren_depth++;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ')':
       if (paren_depth == 0)
 	return 0;
       paren_depth--;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ',':
       if (pstate->comma_terminates && paren_depth == 0)
 	return 0;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '.':
       /* Might be a floating point number.  */
-      if (lexptr[1] >= '0' && lexptr[1] <= '9')
+      if (pstate->lexptr[1] >= '0' && pstate->lexptr[1] <= '9')
 	break;			/* Falls into number code.  */
       else
       {
-	 lexptr++;
+	 pstate->lexptr++;
 	 return DOT;
       }
 
@@ -851,7 +851,7 @@  yylex (void)
     case '@':
     case '~':
     case '&':
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '\'' :
@@ -872,7 +872,7 @@  yylex (void)
 	 error (_("Unterminated string or character constant."));
       yylval.sval.ptr = tokstart + 1;
       yylval.sval.length = namelen - 1;
-      lexptr += namelen + 1;
+      pstate->lexptr += namelen + 1;
 
       if(namelen == 2)  	/* Single character */
       {
@@ -918,7 +918,7 @@  yylex (void)
 	    err_copy[p - tokstart] = 0;
 	    error (_("Invalid number \"%s\"."), err_copy);
 	  }
-	lexptr = p;
+	pstate->lexptr = p;
 	return toktype;
     }
 
@@ -942,7 +942,7 @@  yylex (void)
       return 0;
     }
 
-  lexptr += namelen;
+  pstate->lexptr += namelen;
 
   /*  Lookup special keywords */
   for(i = 0 ; i < (int) (sizeof(keytab) / sizeof(keytab[0])) ; i++)
@@ -1050,8 +1050,8 @@  m2_parse (struct parser_state *par_state)
 static void
 yyerror (const char *msg)
 {
-  if (prev_lexptr)
-    lexptr = prev_lexptr;
+  if (pstate->prev_lexptr)
+    pstate->lexptr = pstate->prev_lexptr;
 
-  error (_("A %s in expression, near `%s'."), msg, lexptr);
+  error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
 }
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index 65874c6327d..4487899ead9 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -1128,10 +1128,10 @@  yylex (void)
 
  retry:
 
-  prev_lexptr = lexptr;
+  pstate->prev_lexptr = pstate->lexptr;
 
-  tokstart = lexptr;
-  explen = strlen (lexptr);
+  tokstart = pstate->lexptr;
+  explen = strlen (pstate->lexptr);
 
   /* See if it is a special token of length 3.  */
   if (explen > 2)
@@ -1141,7 +1141,7 @@  yylex (void)
               || (!isalpha (tokstart[3])
 		  && !isdigit (tokstart[3]) && tokstart[3] != '_')))
         {
-          lexptr += 3;
+          pstate->lexptr += 3;
           yylval.opcode = tokentab3[i].opcode;
           return tokentab3[i].token;
         }
@@ -1154,7 +1154,7 @@  yylex (void)
               || (!isalpha (tokstart[2])
 		  && !isdigit (tokstart[2]) && tokstart[2] != '_')))
         {
-          lexptr += 2;
+          pstate->lexptr += 2;
           yylval.opcode = tokentab2[i].opcode;
           return tokentab2[i].token;
         }
@@ -1170,31 +1170,31 @@  yylex (void)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      pstate->lexptr++;
       goto retry;
 
     case '\'':
       /* We either have a character constant ('0' or '\177' for example)
 	 or we have a quoted symbol reference ('foo(int,int)' in object pascal
 	 for example).  */
-      lexptr++;
-      c = *lexptr++;
+      pstate->lexptr++;
+      c = *pstate->lexptr++;
       if (c == '\\')
-	c = parse_escape (pstate->gdbarch (), &lexptr);
+	c = parse_escape (pstate->gdbarch (), &pstate->lexptr);
       else if (c == '\'')
 	error (_("Empty character constant."));
 
       yylval.typed_val_int.val = c;
       yylval.typed_val_int.type = parse_type (pstate)->builtin_char;
 
-      c = *lexptr++;
+      c = *pstate->lexptr++;
       if (c != '\'')
 	{
 	  namelen = skip_quoted (tokstart) - tokstart;
 	  if (namelen > 2)
 	    {
-	      lexptr = tokstart + namelen;
-	      if (lexptr[-1] != '\'')
+	      pstate->lexptr = tokstart + namelen;
+	      if (pstate->lexptr[-1] != '\'')
 		error (_("Unmatched single quote."));
 	      namelen -= 2;
               tokstart++;
@@ -1207,25 +1207,25 @@  yylex (void)
 
     case '(':
       paren_depth++;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ')':
       if (paren_depth == 0)
 	return 0;
       paren_depth--;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case ',':
       if (pstate->comma_terminates && paren_depth == 0)
 	return 0;
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '.':
       /* Might be a floating point number.  */
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (pstate->lexptr[1] < '0' || pstate->lexptr[1] > '9')
 	{
 	  goto symbol;		/* Nope, must be a symbol.  */
 	}
@@ -1293,7 +1293,7 @@  yylex (void)
 	    err_copy[p - tokstart] = 0;
 	    error (_("Invalid number \"%s\"."), err_copy);
 	  }
-	lexptr = p;
+	pstate->lexptr = p;
 	return toktype;
       }
 
@@ -1317,7 +1317,7 @@  yylex (void)
     case '{':
     case '}':
     symbol:
-      lexptr++;
+      pstate->lexptr++;
       return c;
 
     case '"':
@@ -1369,7 +1369,7 @@  yylex (void)
       tempbuf[tempbufindex] = '\0';	/* See note above.  */
       yylval.sval.ptr = tempbuf;
       yylval.sval.length = tempbufindex;
-      lexptr = tokptr;
+      pstate->lexptr = tokptr;
       return (STRING);
     }
 
@@ -1420,7 +1420,7 @@  yylex (void)
       return 0;
     }
 
-  lexptr += namelen;
+  pstate->lexptr += namelen;
 
   tryname:
 
@@ -1616,7 +1616,7 @@  yylex (void)
 	     us whether a type is nested), we just ignore the
 	     containing type.  */
 
-	  p = lexptr;
+	  p = pstate->lexptr;
 	  best_sym = sym;
 	  while (1)
 	    {
@@ -1661,7 +1661,7 @@  yylex (void)
 			  if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
 			    {
 			      best_sym = cur_sym;
-			      lexptr = p;
+			      pstate->lexptr = p;
 			    }
 			  else
 			    break;
@@ -1734,8 +1734,8 @@  pascal_parse (struct parser_state *par_state)
 static void
 yyerror (const char *msg)
 {
-  if (prev_lexptr)
-    lexptr = prev_lexptr;
+  if (pstate->prev_lexptr)
+    pstate->lexptr = pstate->prev_lexptr;
 
-  error (_("A %s in expression, near `%s'."), msg, lexptr);
+  error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
 }
diff --git a/gdb/parse.c b/gdb/parse.c
index 617ff70d67e..5692e23386b 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -69,8 +69,6 @@  const struct exp_descriptor exp_descriptor_standard =
 innermost_block_tracker innermost_block;
 int arglist_len;
 static struct type_stack type_stack;
-const char *lexptr;
-const char *prev_lexptr;
 
 /* True if parsing an expression to attempt completion.  */
 int parse_completion;
@@ -1112,16 +1110,13 @@  parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
   const struct language_defn *lang = NULL;
   int subexp;
 
-  lexptr = *stringptr;
-  prev_lexptr = NULL;
-
   type_stack.elements.clear ();
   expout_last_struct = -1;
   expout_tag_completion_type = TYPE_CODE_UNDEF;
   expout_completion_name.reset ();
   innermost_block.reset (tracker_types);
 
-  if (lexptr == 0 || *lexptr == 0)
+  if (*stringptr == 0 || **stringptr == 0)
     error_no_arg (_("expression to compute"));
 
   std::vector<int> funcalls;
@@ -1184,7 +1179,7 @@  parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
      to the value matching SELECTED_FRAME as set by get_current_arch.  */
 
   parser_state ps (lang, get_current_arch (), expression_context_block,
-		   expression_context_pc, comma);
+		   expression_context_pc, comma, *stringptr);
 
   scoped_restore_current_language lang_saver;
   set_language (lang->la_language);
@@ -1223,7 +1218,7 @@  parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
   if (expressiondebug)
     dump_prefix_expression (result.get (), gdb_stdlog);
 
-  *stringptr = lexptr;
+  *stringptr = ps.lexptr;
   return result;
 }
 
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index f2bb18fd9c7..66828e0f772 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -89,11 +89,13 @@  struct parser_state : public expr_builder
 		struct gdbarch *gdbarch,
 		const struct block *context_block,
 		CORE_ADDR context_pc,
-		int comma)
+		int comma,
+		const char *input)
     : expr_builder (lang, gdbarch),
       expression_context_block (context_block),
       expression_context_pc (context_pc),
-      comma_terminates (comma)
+      comma_terminates (comma),
+      lexptr (input)
   {
   }
 
@@ -114,6 +116,15 @@  struct parser_state : public expr_builder
   /* Nonzero means stop parsing on first comma (if not within parentheses).  */
 
   int comma_terminates;
+
+  /* During parsing of a C expression, the pointer to the next character
+     is in this variable.  */
+
+  const char *lexptr;
+
+  /* After a token has been recognized, this variable points to it.
+     Currently used only for error reporting.  */
+  const char *prev_lexptr = nullptr;
 };
 
 /* When parsing expressions we track the innermost block that was
@@ -352,15 +363,6 @@  extern void null_post_parser (expression_up *, int);
 
 extern bool parse_float (const char *p, int len,
 			 const struct type *type, gdb_byte *data);
-
-/* During parsing of a C expression, the pointer to the next character
-   is in this variable.  */
-
-extern const char *lexptr;
-
-/* After a token has been recognized, this variable points to it.
-   Currently used only for error reporting.  */
-extern const char *prev_lexptr;
 
 /* These codes indicate operator precedences for expression printing,
    least tightly binding first.  */
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
index 2f2cc8f31fe..782117e93e2 100644
--- a/gdb/rust-exp.y
+++ b/gdb/rust-exp.y
@@ -117,7 +117,6 @@  struct rust_parser;
 static int rustyylex (YYSTYPE *, rust_parser *);
 static void rustyyerror (rust_parser *parser, const char *msg);
 
-static void rust_push_back (char c);
 static struct stoken make_stoken (const char *);
 static struct block_symbol rust_lookup_symbol (const char *name,
 					       const struct block *block,
@@ -237,6 +236,10 @@  struct rust_parser
   int lex_number (YYSTYPE *lvalp);
   int lex_string (YYSTYPE *lvalp);
   int lex_identifier (YYSTYPE *lvalp);
+  uint32_t lex_hex (int min, int max);
+  uint32_t lex_escape (int is_byte);
+  int lex_operator (YYSTYPE *lvalp);
+  void push_back (char c);
 
   struct type *rust_lookup_type (const char *name, const struct block *block);
   std::vector<struct type *> convert_params_to_types (rust_op_vector *params);
@@ -855,7 +858,7 @@  identifier_path_for_expr:
 |	identifier_path_for_expr COLONCOLON '<' type_list RSH
 		{
 		  $$ = parser->ast_path ($1->left.sval, $4);
-		  rust_push_back ('>');
+		  parser->push_back ('>');
 		}
 ;
 
@@ -898,7 +901,7 @@  identifier_path_for_type:
 |	just_identifiers_for_type '<' type_list RSH
 		{
 		  $$ = parser->ast_path ($1->left.sval, $3);
-		  rust_push_back ('>');
+		  parser->push_back ('>');
 		}
 ;
 
@@ -1111,8 +1114,8 @@  update_innermost_block (struct block_symbol sym)
 /* Lex a hex number with at least MIN digits and at most MAX
    digits.  */
 
-static uint32_t
-lex_hex (int min, int max)
+uint32_t
+rust_parser::lex_hex (int min, int max)
 {
   uint32_t result = 0;
   int len = 0;
@@ -1120,18 +1123,18 @@  lex_hex (int min, int max)
   int check_max = min == max;
 
   while ((check_max ? len <= max : 1)
-	 && ((lexptr[0] >= 'a' && lexptr[0] <= 'f')
-	     || (lexptr[0] >= 'A' && lexptr[0] <= 'F')
-	     || (lexptr[0] >= '0' && lexptr[0] <= '9')))
+	 && ((pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'f')
+	     || (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'F')
+	     || (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9')))
     {
       result *= 16;
-      if (lexptr[0] >= 'a' && lexptr[0] <= 'f')
-	result = result + 10 + lexptr[0] - 'a';
-      else if (lexptr[0] >= 'A' && lexptr[0] <= 'F')
-	result = result + 10 + lexptr[0] - 'A';
+      if (pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'f')
+	result = result + 10 + pstate->lexptr[0] - 'a';
+      else if (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'F')
+	result = result + 10 + pstate->lexptr[0] - 'A';
       else
-	result = result + lexptr[0] - '0';
-      ++lexptr;
+	result = result + pstate->lexptr[0] - '0';
+      ++pstate->lexptr;
       ++len;
     }
 
@@ -1149,65 +1152,65 @@  lex_hex (int min, int max)
 /* Lex an escape.  IS_BYTE is true if we're lexing a byte escape;
    otherwise we're lexing a character escape.  */
 
-static uint32_t
-lex_escape (int is_byte)
+uint32_t
+rust_parser::lex_escape (int is_byte)
 {
   uint32_t result;
 
-  gdb_assert (lexptr[0] == '\\');
-  ++lexptr;
-  switch (lexptr[0])
+  gdb_assert (pstate->lexptr[0] == '\\');
+  ++pstate->lexptr;
+  switch (pstate->lexptr[0])
     {
     case 'x':
-      ++lexptr;
+      ++pstate->lexptr;
       result = lex_hex (2, 2);
       break;
 
     case 'u':
       if (is_byte)
 	error (_("Unicode escape in byte literal"));
-      ++lexptr;
-      if (lexptr[0] != '{')
+      ++pstate->lexptr;
+      if (pstate->lexptr[0] != '{')
 	error (_("Missing '{' in Unicode escape"));
-      ++lexptr;
+      ++pstate->lexptr;
       result = lex_hex (1, 6);
       /* Could do range checks here.  */
-      if (lexptr[0] != '}')
+      if (pstate->lexptr[0] != '}')
 	error (_("Missing '}' in Unicode escape"));
-      ++lexptr;
+      ++pstate->lexptr;
       break;
 
     case 'n':
       result = '\n';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
     case 'r':
       result = '\r';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
     case 't':
       result = '\t';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
     case '\\':
       result = '\\';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
     case '0':
       result = '\0';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
     case '\'':
       result = '\'';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
     case '"':
       result = '"';
-      ++lexptr;
+      ++pstate->lexptr;
       break;
 
     default:
-      error (_("Invalid escape \\%c in literal"), lexptr[0]);
+      error (_("Invalid escape \\%c in literal"), pstate->lexptr[0]);
     }
 
   return result;
@@ -1221,25 +1224,25 @@  rust_parser::lex_character (YYSTYPE *lvalp)
   int is_byte = 0;
   uint32_t value;
 
-  if (lexptr[0] == 'b')
+  if (pstate->lexptr[0] == 'b')
     {
       is_byte = 1;
-      ++lexptr;
+      ++pstate->lexptr;
     }
-  gdb_assert (lexptr[0] == '\'');
-  ++lexptr;
+  gdb_assert (pstate->lexptr[0] == '\'');
+  ++pstate->lexptr;
   /* This should handle UTF-8 here.  */
-  if (lexptr[0] == '\\')
+  if (pstate->lexptr[0] == '\\')
     value = lex_escape (is_byte);
   else
     {
-      value = lexptr[0] & 0xff;
-      ++lexptr;
+      value = pstate->lexptr[0] & 0xff;
+      ++pstate->lexptr;
     }
 
-  if (lexptr[0] != '\'')
+  if (pstate->lexptr[0] != '\'')
     error (_("Unterminated character literal"));
-  ++lexptr;
+  ++pstate->lexptr;
 
   lvalp->typed_val_int.val = value;
   lvalp->typed_val_int.type = get_type (is_byte ? "u8" : "char");
@@ -1285,15 +1288,15 @@  ends_raw_string (const char *str, int n)
 int
 rust_parser::lex_string (YYSTYPE *lvalp)
 {
-  int is_byte = lexptr[0] == 'b';
+  int is_byte = pstate->lexptr[0] == 'b';
   int raw_length;
 
   if (is_byte)
-    ++lexptr;
-  raw_length = starts_raw_string (lexptr);
-  lexptr += raw_length;
-  gdb_assert (lexptr[0] == '"');
-  ++lexptr;
+    ++pstate->lexptr;
+  raw_length = starts_raw_string (pstate->lexptr);
+  pstate->lexptr += raw_length;
+  gdb_assert (pstate->lexptr[0] == '"');
+  ++pstate->lexptr;
 
   while (1)
     {
@@ -1301,29 +1304,30 @@  rust_parser::lex_string (YYSTYPE *lvalp)
 
       if (raw_length > 0)
 	{
-	  if (lexptr[0] == '"' && ends_raw_string (lexptr, raw_length - 1))
+	  if (pstate->lexptr[0] == '"' && ends_raw_string (pstate->lexptr,
+							   raw_length - 1))
 	    {
 	      /* Exit with lexptr pointing after the final "#".  */
-	      lexptr += raw_length;
+	      pstate->lexptr += raw_length;
 	      break;
 	    }
-	  else if (lexptr[0] == '\0')
+	  else if (pstate->lexptr[0] == '\0')
 	    error (_("Unexpected EOF in string"));
 
-	  value = lexptr[0] & 0xff;
+	  value = pstate->lexptr[0] & 0xff;
 	  if (is_byte && value > 127)
 	    error (_("Non-ASCII value in raw byte string"));
 	  obstack_1grow (&obstack, value);
 
-	  ++lexptr;
+	  ++pstate->lexptr;
 	}
-      else if (lexptr[0] == '"')
+      else if (pstate->lexptr[0] == '"')
 	{
 	  /* Make sure to skip the quote.  */
-	  ++lexptr;
+	  ++pstate->lexptr;
 	  break;
 	}
-      else if (lexptr[0] == '\\')
+      else if (pstate->lexptr[0] == '\\')
 	{
 	  value = lex_escape (is_byte);
 
@@ -1334,15 +1338,15 @@  rust_parser::lex_string (YYSTYPE *lvalp)
 				       sizeof (value), sizeof (value),
 				       &obstack, translit_none);
 	}
-      else if (lexptr[0] == '\0')
+      else if (pstate->lexptr[0] == '\0')
 	error (_("Unexpected EOF in string"));
       else
 	{
-	  value = lexptr[0] & 0xff;
+	  value = pstate->lexptr[0] & 0xff;
 	  if (is_byte && value > 127)
 	    error (_("Non-ASCII value in byte string"));
 	  obstack_1grow (&obstack, value);
-	  ++lexptr;
+	  ++pstate->lexptr;
 	}
     }
 
@@ -1382,27 +1386,27 @@  rust_identifier_start_p (char c)
 int
 rust_parser::lex_identifier (YYSTYPE *lvalp)
 {
-  const char *start = lexptr;
+  const char *start = pstate->lexptr;
   unsigned int length;
   const struct token_info *token;
   int i;
-  int is_gdb_var = lexptr[0] == '$';
+  int is_gdb_var = pstate->lexptr[0] == '$';
 
-  gdb_assert (rust_identifier_start_p (lexptr[0]));
+  gdb_assert (rust_identifier_start_p (pstate->lexptr[0]));
 
-  ++lexptr;
+  ++pstate->lexptr;
 
   /* For the time being this doesn't handle Unicode rules.  Non-ASCII
      identifiers are gated anyway.  */
-  while ((lexptr[0] >= 'a' && lexptr[0] <= 'z')
-	 || (lexptr[0] >= 'A' && lexptr[0] <= 'Z')
-	 || lexptr[0] == '_'
-	 || (is_gdb_var && lexptr[0] == '$')
-	 || (lexptr[0] >= '0' && lexptr[0] <= '9'))
-    ++lexptr;
+  while ((pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'z')
+	 || (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'Z')
+	 || pstate->lexptr[0] == '_'
+	 || (is_gdb_var && pstate->lexptr[0] == '$')
+	 || (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9'))
+    ++pstate->lexptr;
 
 
-  length = lexptr - start;
+  length = pstate->lexptr - start;
   token = NULL;
   for (i = 0; i < ARRAY_SIZE (identifier_tokens); ++i)
     {
@@ -1419,28 +1423,28 @@  rust_parser::lex_identifier (YYSTYPE *lvalp)
       if (token->value == 0)
 	{
 	  /* Leave the terminating token alone.  */
-	  lexptr = start;
+	  pstate->lexptr = start;
 	  return 0;
 	}
     }
   else if (token == NULL
 	   && (strncmp (start, "thread", length) == 0
 	       || strncmp (start, "task", length) == 0)
-	   && space_then_number (lexptr))
+	   && space_then_number (pstate->lexptr))
     {
       /* "task" or "thread" followed by a number terminates the
 	 parse, per gdb rules.  */
-      lexptr = start;
+      pstate->lexptr = start;
       return 0;
     }
 
-  if (token == NULL || (parse_completion && lexptr[0] == '\0'))
+  if (token == NULL || (parse_completion && pstate->lexptr[0] == '\0'))
     lvalp->sval = make_stoken (copy_name (start, length));
 
-  if (parse_completion && lexptr[0] == '\0')
+  if (parse_completion && pstate->lexptr[0] == '\0')
     {
       /* Prevent rustyylex from returning two COMPLETE tokens.  */
-      prev_lexptr = lexptr;
+      pstate->prev_lexptr = pstate->lexptr;
       return COMPLETE;
     }
 
@@ -1453,18 +1457,18 @@  rust_parser::lex_identifier (YYSTYPE *lvalp)
 
 /* Lex an operator.  */
 
-static int
-lex_operator (YYSTYPE *lvalp)
+int
+rust_parser::lex_operator (YYSTYPE *lvalp)
 {
   const struct token_info *token = NULL;
   int i;
 
   for (i = 0; i < ARRAY_SIZE (operator_tokens); ++i)
     {
-      if (strncmp (operator_tokens[i].name, lexptr,
+      if (strncmp (operator_tokens[i].name, pstate->lexptr,
 		   strlen (operator_tokens[i].name)) == 0)
 	{
-	  lexptr += strlen (operator_tokens[i].name);
+	  pstate->lexptr += strlen (operator_tokens[i].name);
 	  token = &operator_tokens[i];
 	  break;
 	}
@@ -1476,7 +1480,7 @@  lex_operator (YYSTYPE *lvalp)
       return token->value;
     }
 
-  return *lexptr++;
+  return *pstate->lexptr++;
 }
 
 /* Lex a number.  */
@@ -1495,7 +1499,8 @@  rust_parser::lex_number (YYSTYPE *lvalp)
   int type_index = -1;
   int i;
 
-  match = regexec (&number_regex, lexptr, ARRAY_SIZE (subexps), subexps, 0);
+  match = regexec (&number_regex, pstate->lexptr, ARRAY_SIZE (subexps),
+		   subexps, 0);
   /* Failure means the regexp is broken.  */
   gdb_assert (match == 0);
 
@@ -1539,9 +1544,9 @@  rust_parser::lex_number (YYSTYPE *lvalp)
      a request for a trait method call, not a syntax error involving
      the floating point number "23.".  */
   gdb_assert (subexps[0].rm_eo > 0);
-  if (lexptr[subexps[0].rm_eo - 1] == '.')
+  if (pstate->lexptr[subexps[0].rm_eo - 1] == '.')
     {
-      const char *next = skip_spaces (&lexptr[subexps[0].rm_eo]);
+      const char *next = skip_spaces (&pstate->lexptr[subexps[0].rm_eo]);
 
       if (rust_identifier_start_p (*next) || *next == '.')
 	{
@@ -1559,7 +1564,8 @@  rust_parser::lex_number (YYSTYPE *lvalp)
   if (type_name == NULL)
     {
       gdb_assert (type_index != -1);
-      type_name_holder = std::string (lexptr + subexps[type_index].rm_so,
+      type_name_holder = std::string ((pstate->lexptr
+				       + subexps[type_index].rm_so),
 				      (subexps[type_index].rm_eo
 				       - subexps[type_index].rm_so));
       type_name = type_name_holder.c_str ();
@@ -1570,16 +1576,16 @@  rust_parser::lex_number (YYSTYPE *lvalp)
 
   /* Copy the text of the number and remove the "_"s.  */
   std::string number;
-  for (i = 0; i < end_index && lexptr[i]; ++i)
+  for (i = 0; i < end_index && pstate->lexptr[i]; ++i)
     {
-      if (lexptr[i] == '_')
+      if (pstate->lexptr[i] == '_')
 	could_be_decimal = 0;
       else
-	number.push_back (lexptr[i]);
+	number.push_back (pstate->lexptr[i]);
     }
 
   /* Advance past the match.  */
-  lexptr += subexps[0].rm_eo;
+  pstate->lexptr += subexps[0].rm_eo;
 
   /* Parse the number.  */
   if (is_integer)
@@ -1627,18 +1633,22 @@  rust_parser::lex_number (YYSTYPE *lvalp)
 static int
 rustyylex (YYSTYPE *lvalp, rust_parser *parser)
 {
+  struct parser_state *pstate = parser->pstate;
+
   /* Skip all leading whitespace.  */
-  while (lexptr[0] == ' ' || lexptr[0] == '\t' || lexptr[0] == '\r'
-	 || lexptr[0] == '\n')
-    ++lexptr;
+  while (pstate->lexptr[0] == ' '
+	 || pstate->lexptr[0] == '\t'
+	 || pstate->lexptr[0] == '\r'
+	 || pstate->lexptr[0] == '\n')
+    ++pstate->lexptr;
 
   /* If we hit EOF and we're completing, then return COMPLETE -- maybe
      we're completing an empty string at the end of a field_expr.
      But, we don't want to return two COMPLETE tokens in a row.  */
-  if (lexptr[0] == '\0' && lexptr == prev_lexptr)
+  if (pstate->lexptr[0] == '\0' && pstate->lexptr == pstate->prev_lexptr)
     return 0;
-  prev_lexptr = lexptr;
-  if (lexptr[0] == '\0')
+  pstate->prev_lexptr = pstate->lexptr;
+  if (pstate->lexptr[0] == '\0')
     {
       if (parse_completion)
 	{
@@ -1648,49 +1658,49 @@  rustyylex (YYSTYPE *lvalp, rust_parser *parser)
       return 0;
     }
 
-  if (lexptr[0] >= '0' && lexptr[0] <= '9')
+  if (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9')
     return parser->lex_number (lvalp);
-  else if (lexptr[0] == 'b' && lexptr[1] == '\'')
+  else if (pstate->lexptr[0] == 'b' && pstate->lexptr[1] == '\'')
     return parser->lex_character (lvalp);
-  else if (lexptr[0] == 'b' && lexptr[1] == '"')
+  else if (pstate->lexptr[0] == 'b' && pstate->lexptr[1] == '"')
     return parser->lex_string (lvalp);
-  else if (lexptr[0] == 'b' && starts_raw_string (lexptr + 1))
+  else if (pstate->lexptr[0] == 'b' && starts_raw_string (pstate->lexptr + 1))
     return parser->lex_string (lvalp);
-  else if (starts_raw_string (lexptr))
+  else if (starts_raw_string (pstate->lexptr))
     return parser->lex_string (lvalp);
-  else if (rust_identifier_start_p (lexptr[0]))
+  else if (rust_identifier_start_p (pstate->lexptr[0]))
     return parser->lex_identifier (lvalp);
-  else if (lexptr[0] == '"')
+  else if (pstate->lexptr[0] == '"')
     return parser->lex_string (lvalp);
-  else if (lexptr[0] == '\'')
+  else if (pstate->lexptr[0] == '\'')
     return parser->lex_character (lvalp);
-  else if (lexptr[0] == '}' || lexptr[0] == ']')
+  else if (pstate->lexptr[0] == '}' || pstate->lexptr[0] == ']')
     {
       /* Falls through to lex_operator.  */
       --parser->paren_depth;
     }
-  else if (lexptr[0] == '(' || lexptr[0] == '{')
+  else if (pstate->lexptr[0] == '(' || pstate->lexptr[0] == '{')
     {
       /* Falls through to lex_operator.  */
       ++parser->paren_depth;
     }
-  else if (lexptr[0] == ',' && parser->pstate->comma_terminates
+  else if (pstate->lexptr[0] == ',' && pstate->comma_terminates
 	   && parser->paren_depth == 0)
     return 0;
 
-  return lex_operator (lvalp);
+  return parser->lex_operator (lvalp);
 }
 
 /* Push back a single character to be re-lexed.  */
 
-static void
-rust_push_back (char c)
+void
+rust_parser::push_back (char c)
 {
   /* Can't be called before any lexing.  */
-  gdb_assert (prev_lexptr != NULL);
+  gdb_assert (pstate->prev_lexptr != NULL);
 
-  --lexptr;
-  gdb_assert (*lexptr == c);
+  --pstate->lexptr;
+  gdb_assert (*pstate->lexptr == c);
 }
 
 
@@ -2545,7 +2555,9 @@  rust_parse (struct parser_state *state)
 static void
 rustyyerror (rust_parser *parser, const char *msg)
 {
-  const char *where = prev_lexptr ? prev_lexptr : lexptr;
+  const char *where = (parser->pstate->prev_lexptr
+		       ? parser->pstate->prev_lexptr
+		       : parser->pstate->lexptr);
   error (_("%s in expression, near `%s'."), msg, where);
 }
 
@@ -2558,8 +2570,8 @@  rustyyerror (rust_parser *parser, const char *msg)
 static void
 rust_lex_test_init (rust_parser *parser, const char *input)
 {
-  prev_lexptr = NULL;
-  lexptr = input;
+  parser->pstate->prev_lexptr = NULL;
+  parser->pstate->lexptr = input;
   parser->paren_depth = 0;
 }
 
@@ -2635,7 +2647,7 @@  rust_lex_test_sequence (rust_parser *parser, const char *input, int len,
 {
   int i;
 
-  lexptr = input;
+  parser->pstate->lexptr = input;
   parser->paren_depth = 0;
 
   for (i = 0; i < len; ++i)
@@ -2696,7 +2708,7 @@  rust_lex_test_push_back (rust_parser *parser)
   SELF_CHECK (token == COMPOUND_ASSIGN);
   SELF_CHECK (lval.opcode == BINOP_RSH);
 
-  rust_push_back ('=');
+  parser->push_back ('=');
 
   token = rustyylex (&lval, parser);
   SELF_CHECK (token == '=');
@@ -2714,7 +2726,7 @@  rust_lex_tests (void)
 
   // Set up dummy "parser", so that rust_type works.
   struct parser_state ps (&rust_language_defn, target_gdbarch (),
-			  nullptr, 0, 0);
+			  nullptr, 0, 0, nullptr);
   rust_parser parser (&ps);
 
   rust_lex_test_one (&parser, "", 0);