Add `set print array-indexes' tests for C/C++ arrays
[binutils-gdb.git] / gdb / ada-exp.y
index 4b8bb93a0635cee75aedd6fb89d1e926337bd5ca..16ba336df4aa45b93c8368fa812e4b3e991978dd 100644 (file)
@@ -1,23 +1,20 @@
 /* YACC parser for Ada expressions, for GDB.
-   Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000, 2003, 2004,
-   2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Parse an Ada expression from text in a string,
    and return the result as a  struct expression  pointer.
@@ -39,7 +36,6 @@ Boston, MA 02110-1301, USA.  */
 %{
 
 #include "defs.h"
-#include "gdb_string.h"
 #include <ctype.h>
 #include "expression.h"
 #include "value.h"
@@ -51,113 +47,351 @@ Boston, MA 02110-1301, USA.  */
 #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
 #include "frame.h"
 #include "block.h"
+#include "ada-exp.h"
 
-#define parse_type builtin_type (parse_gdbarch)
-
-/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
-   as well as gratuitiously global symbol names, so we can have multiple
-   yacc generated parsers in gdb.  These are only the variables
-   produced by yacc.  If other parser generators (bison, byacc, etc) produce
-   additional global names that conflict at link time, then those parser
-   generators need to be fixed instead of adding those names to this list.  */
-
-/* NOTE: This is clumsy, especially since BISON and FLEX provide --prefix
-   options.  I presume we are maintaining it to accommodate systems
-   without BISON?  (PNH) */
-
-#define        yymaxdepth ada_maxdepth
-#define        yyparse _ada_parse      /* ada_parse calls this after  initialization */
-#define        yylex   ada_lex
-#define        yyerror ada_error
-#define        yylval  ada_lval
-#define        yychar  ada_char
-#define        yydebug ada_debug
-#define        yypact  ada_pact
-#define        yyr1    ada_r1
-#define        yyr2    ada_r2
-#define        yydef   ada_def
-#define        yychk   ada_chk
-#define        yypgo   ada_pgo
-#define        yyact   ada_act
-#define        yyexca  ada_exca
-#define yyerrflag ada_errflag
-#define yynerrs        ada_nerrs
-#define        yyps    ada_ps
-#define        yypv    ada_pv
-#define        yys     ada_s
-#define        yy_yys  ada_yys
-#define        yystate ada_state
-#define        yytmp   ada_tmp
-#define        yyv     ada_v
-#define        yy_yyv  ada_yyv
-#define        yyval   ada_val
-#define        yylloc  ada_lloc
-#define yyreds ada_reds                /* With YYDEBUG defined */
-#define yytoks ada_toks                /* With YYDEBUG defined */
-#define yyname ada_name                /* With YYDEBUG defined */
-#define yyrule ada_rule                /* With YYDEBUG defined */
-
-#ifndef YYDEBUG
-#define        YYDEBUG 1               /* Default to yydebug support */
-#endif
-
-#define YYFPRINTF parser_fprintf
+#define parse_type(ps) builtin_type (ps->gdbarch ())
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
+   etc).  */
+#define GDB_YY_REMAP_PREFIX ada_
+#include "yy-remap.h"
 
 struct name_info {
   struct symbol *sym;
   struct minimal_symbol *msym;
-  struct block *block;
+  const struct block *block;
   struct stoken stoken;
 };
 
-static struct stoken empty_stoken = { "", 0 };
+/* The state of the parser, used internally when we are parsing the
+   expression.  */
 
-/* If expression is in the context of TYPE'(...), then TYPE, else
- * NULL.  */
-static struct type *type_qualifier;
+static struct parser_state *pstate = NULL;
 
 int yyparse (void);
 
 static int yylex (void);
 
-void yyerror (char *);
-
-static struct stoken string_to_operator (struct stoken);
+static void yyerror (const char *);
 
-static void write_int (LONGEST, struct type *);
+static void write_int (struct parser_state *, LONGEST, struct type *);
 
-static void write_object_renaming (struct block *, const char *, int,
+static void write_object_renaming (struct parser_state *,
+                                  const struct block *, const char *, int,
                                   const char *, int);
 
-static struct type* write_var_or_type (struct block *, struct stoken);
+static struct type* write_var_or_type (struct parser_state *,
+                                      const struct block *, struct stoken);
+
+static void write_name_assoc (struct parser_state *, struct stoken);
+
+static const struct block *block_lookup (const struct block *, const char *);
+
+static void write_ambiguous_var (struct parser_state *,
+                                const struct block *, const char *, int);
+
+static struct type *type_int (struct parser_state *);
+
+static struct type *type_long (struct parser_state *);
+
+static struct type *type_long_long (struct parser_state *);
+
+static struct type *type_long_double (struct parser_state *);
+
+static struct type *type_char (struct parser_state *);
+
+static struct type *type_boolean (struct parser_state *);
+
+static struct type *type_system_address (struct parser_state *);
+
+using namespace expr;
 
-static void write_name_assoc (struct stoken);
+/* Handle Ada type resolution for OP.  DEPROCEDURE_P and CONTEXT_TYPE
+   are passed to the resolve method, if called.  */
+static operation_up
+resolve (operation_up &&op, bool deprocedure_p, struct type *context_type)
+{
+  operation_up result = std::move (op);
+  ada_resolvable *res = dynamic_cast<ada_resolvable *> (result.get ());
+  if (res != nullptr)
+    return res->replace (std::move (result),
+                        pstate->expout.get (),
+                        deprocedure_p,
+                        pstate->parse_completion,
+                        pstate->block_tracker,
+                        context_type);
+  return result;
+}
 
-static void write_exp_op_with_string (enum exp_opcode, struct stoken);
+/* Like parser_state::pop, but handles Ada type resolution.
+   DEPROCEDURE_P and CONTEXT_TYPE are passed to the resolve method, if
+   called.  */
+static operation_up
+ada_pop (bool deprocedure_p = true, struct type *context_type = nullptr)
+{
+  /* Of course it's ok to call parser_state::pop here... */
+  return resolve (pstate->pop (), deprocedure_p, context_type);
+}
 
-static struct block *block_lookup (struct block *, char *);
+/* Like parser_state::wrap, but use ada_pop to pop the value.  */
+template<typename T>
+void
+ada_wrap ()
+{
+  operation_up arg = ada_pop ();
+  pstate->push_new<T> (std::move (arg));
+}
 
-static LONGEST convert_char_literal (struct type *, LONGEST);
+/* Create and push an address-of operation, as appropriate for Ada.
+   If TYPE is not NULL, the resulting operation will be wrapped in a
+   cast to TYPE.  */
+static void
+ada_addrof (struct type *type = nullptr)
+{
+  operation_up arg = ada_pop (false);
+  operation_up addr = make_operation<unop_addr_operation> (std::move (arg));
+  operation_up wrapped
+    = make_operation<ada_wrapped_operation> (std::move (addr));
+  if (type != nullptr)
+    wrapped = make_operation<unop_cast_operation> (std::move (wrapped), type);
+  pstate->push (std::move (wrapped));
+}
 
-static void write_ambiguous_var (struct block *, char *, int);
+/* Handle operator overloading.  Either returns a function all
+   operation wrapping the arguments, or it returns null, leaving the
+   caller to construct the appropriate operation.  If RHS is null, a
+   unary operator is assumed.  */
+static operation_up
+maybe_overload (enum exp_opcode op, operation_up &lhs, operation_up &rhs)
+{
+  struct value *args[2];
+
+  int nargs = 1;
+  args[0] = lhs->evaluate (nullptr, pstate->expout.get (),
+                          EVAL_AVOID_SIDE_EFFECTS);
+  if (rhs == nullptr)
+    args[1] = nullptr;
+  else
+    {
+      args[1] = rhs->evaluate (nullptr, pstate->expout.get (),
+                              EVAL_AVOID_SIDE_EFFECTS);
+      ++nargs;
+    }
 
-static struct type *type_int (void);
+  block_symbol fn = ada_find_operator_symbol (op, pstate->parse_completion,
+                                             nargs, args);
+  if (fn.symbol == nullptr)
+    return {};
+
+  if (symbol_read_needs_frame (fn.symbol))
+    pstate->block_tracker->update (fn.block, INNERMOST_BLOCK_FOR_SYMBOLS);
+  operation_up callee = make_operation<ada_var_value_operation> (fn);
+
+  std::vector<operation_up> argvec;
+  argvec.push_back (std::move (lhs));
+  if (rhs != nullptr)
+    argvec.push_back (std::move (rhs));
+  return make_operation<ada_funcall_operation> (std::move (callee),
+                                               std::move (argvec));
+}
 
-static struct type *type_long (void);
+/* Like parser_state::wrap, but use ada_pop to pop the value, and
+   handle unary overloading.  */
+template<typename T>
+void
+ada_wrap_overload (enum exp_opcode op)
+{
+  operation_up arg = ada_pop ();
+  operation_up empty;
 
-static struct type *type_long_long (void);
+  operation_up call = maybe_overload (op, arg, empty);
+  if (call == nullptr)
+    call = make_operation<T> (std::move (arg));
+  pstate->push (std::move (call));
+}
 
-static struct type *type_float (void);
+/* A variant of parser_state::wrap2 that uses ada_pop to pop both
+   operands, and then pushes a new Ada-wrapped operation of the
+   template type T.  */
+template<typename T>
+void
+ada_un_wrap2 (enum exp_opcode op)
+{
+  operation_up rhs = ada_pop ();
+  operation_up lhs = ada_pop ();
 
-static struct type *type_double (void);
+  operation_up wrapped = maybe_overload (op, lhs, rhs);
+  if (wrapped == nullptr)
+    {
+      wrapped = make_operation<T> (std::move (lhs), std::move (rhs));
+      wrapped = make_operation<ada_wrapped_operation> (std::move (wrapped));
+    }
+  pstate->push (std::move (wrapped));
+}
 
-static struct type *type_long_double (void);
+/* A variant of parser_state::wrap2 that uses ada_pop to pop both
+   operands.  Unlike ada_un_wrap2, ada_wrapped_operation is not
+   used.  */
+template<typename T>
+void
+ada_wrap2 (enum exp_opcode op)
+{
+  operation_up rhs = ada_pop ();
+  operation_up lhs = ada_pop ();
+  operation_up call = maybe_overload (op, lhs, rhs);
+  if (call == nullptr)
+    call = make_operation<T> (std::move (lhs), std::move (rhs));
+  pstate->push (std::move (call));
+}
 
-static struct type *type_char (void);
+/* A variant of parser_state::wrap2 that uses ada_pop to pop both
+   operands.  OP is also passed to the constructor of the new binary
+   operation.  */
+template<typename T>
+void
+ada_wrap_op (enum exp_opcode op)
+{
+  operation_up rhs = ada_pop ();
+  operation_up lhs = ada_pop ();
+  operation_up call = maybe_overload (op, lhs, rhs);
+  if (call == nullptr)
+    call = make_operation<T> (op, std::move (lhs), std::move (rhs));
+  pstate->push (std::move (call));
+}
 
-static struct type *type_boolean (void);
+/* Pop three operands using ada_pop, then construct a new ternary
+   operation of type T and push it.  */
+template<typename T>
+void
+ada_wrap3 ()
+{
+  operation_up rhs = ada_pop ();
+  operation_up mid = ada_pop ();
+  operation_up lhs = ada_pop ();
+  pstate->push_new<T> (std::move (lhs), std::move (mid), std::move (rhs));
+}
 
-static struct type *type_system_address (void);
+/* Pop NARGS operands, then a callee operand, and use these to
+   construct and push a new Ada function call operation.  */
+static void
+ada_funcall (int nargs)
+{
+  /* We use the ordinary pop here, because we're going to do
+     resolution in a separate step, in order to handle array
+     indices.  */
+  std::vector<operation_up> args = pstate->pop_vector (nargs);
+  /* Call parser_state::pop here, because we don't want to
+     function-convert the callee slot of a call we're already
+     constructing.  */
+  operation_up callee = pstate->pop ();
+
+  ada_var_value_operation *vvo
+    = dynamic_cast<ada_var_value_operation *> (callee.get ());
+  int array_arity = 0;
+  struct type *callee_t = nullptr;
+  if (vvo == nullptr
+      || SYMBOL_DOMAIN (vvo->get_symbol ()) != UNDEF_DOMAIN)
+    {
+      struct value *callee_v = callee->evaluate (nullptr,
+                                                pstate->expout.get (),
+                                                EVAL_AVOID_SIDE_EFFECTS);
+      callee_t = ada_check_typedef (value_type (callee_v));
+      array_arity = ada_array_arity (callee_t);
+    }
+
+  for (int i = 0; i < nargs; ++i)
+    {
+      struct type *subtype = nullptr;
+      if (i < array_arity)
+       subtype = ada_index_type (callee_t, i + 1, "array type");
+      args[i] = resolve (std::move (args[i]), true, subtype);
+    }
+
+  std::unique_ptr<ada_funcall_operation> funcall
+    (new ada_funcall_operation (std::move (callee), std::move (args)));
+  funcall->resolve (pstate->expout.get (), true, pstate->parse_completion,
+                   pstate->block_tracker, nullptr);
+  pstate->push (std::move (funcall));
+}
+
+/* The components being constructed during this parse.  */
+static std::vector<ada_component_up> components;
+
+/* Create a new ada_component_up of the indicated type and arguments,
+   and push it on the global 'components' vector.  */
+template<typename T, typename... Arg>
+void
+push_component (Arg... args)
+{
+  components.emplace_back (new T (std::forward<Arg> (args)...));
+}
+
+/* Examine the final element of the 'components' vector, and return it
+   as a pointer to an ada_choices_component.  The caller is
+   responsible for ensuring that the final element is in fact an
+   ada_choices_component.  */
+static ada_choices_component *
+choice_component ()
+{
+  ada_component *last = components.back ().get ();
+  ada_choices_component *result = dynamic_cast<ada_choices_component *> (last);
+  gdb_assert (result != nullptr);
+  return result;
+}
+
+/* Pop the most recent component from the global stack, and return
+   it.  */
+static ada_component_up
+pop_component ()
+{
+  ada_component_up result = std::move (components.back ());
+  components.pop_back ();
+  return result;
+}
+
+/* Pop the N most recent components from the global stack, and return
+   them in a vector.  */
+static std::vector<ada_component_up>
+pop_components (int n)
+{
+  std::vector<ada_component_up> result (n);
+  for (int i = 1; i <= n; ++i)
+    result[n - i] = pop_component ();
+  return result;
+}
+
+/* The associations being constructed during this parse.  */
+static std::vector<ada_association_up> associations;
+
+/* Create a new ada_association_up of the indicated type and
+   arguments, and push it on the global 'associations' vector.  */
+template<typename T, typename... Arg>
+void
+push_association (Arg... args)
+{
+  associations.emplace_back (new T (std::forward<Arg> (args)...));
+}
+
+/* Pop the most recent association from the global stack, and return
+   it.  */
+static ada_association_up
+pop_association ()
+{
+  ada_association_up result = std::move (associations.back ());
+  associations.pop_back ();
+  return result;
+}
+
+/* Pop the N most recent associations from the global stack, and
+   return them in a vector.  */
+static std::vector<ada_association_up>
+pop_associations (int n)
+{
+  std::vector<ada_association_up> result (n);
+  for (int i = 1; i <= n; ++i)
+    result[n - i] = pop_association ();
+  return result;
+}
 
 %}
 
@@ -169,18 +403,18 @@ static struct type *type_system_address (void);
       struct type *type;
     } typed_val;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct type *tval;
     struct stoken sval;
-    struct block *bval;
+    const struct block *bval;
     struct internalvar *ivar;
   }
 
 %type <lval> positional_list component_groups component_associations
 %type <lval> aggregate_component_list 
-%type <tval> var_or_type
+%type <tval> var_or_type type_prefix opt_type_prefix
 
 %token <typed_val> INT NULL_PTR CHARLIT
 %token <typed_val_float> FLOAT
@@ -190,13 +424,11 @@ static struct type *type_system_address (void);
 %type <bval> block
 %type <lval> arglist tick_arglist
 
-%type <tval> save_qualifier
-
 %token DOT_ALL
 
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
-%token <sval> SPECIAL_VARIABLE
+%token <sval> DOLLAR_VARIABLE
 
 %nonassoc ASSIGN
 %left _AND_ OR XOR THEN ELSE
@@ -233,66 +465,68 @@ start   : exp1
 /* Expressions, including the sequencing operator.  */
 exp1   :       exp
        |       exp1 ';' exp
-                       { write_exp_elt_opcode (BINOP_COMMA); }
+                       { ada_wrap2<comma_operation> (BINOP_COMMA); }
        |       primary ASSIGN exp   /* Extension for convenience */
-                       { write_exp_elt_opcode (BINOP_ASSIGN); }
+                       {
+                         operation_up rhs = pstate->pop ();
+                         operation_up lhs = ada_pop ();
+                         value *lhs_val
+                           = lhs->evaluate (nullptr, pstate->expout.get (),
+                                            EVAL_AVOID_SIDE_EFFECTS);
+                         rhs = resolve (std::move (rhs), true,
+                                        value_type (lhs_val));
+                         pstate->push_new<ada_assign_operation>
+                           (std::move (lhs), std::move (rhs));
+                       }
        ;
 
 /* Expressions, not including the sequencing operator.  */
 primary :      primary DOT_ALL
-                       { write_exp_elt_opcode (UNOP_IND); }
+                       { ada_wrap<ada_unop_ind_operation> (); }
        ;
 
 primary :      primary DOT_ID
-                       { write_exp_op_with_string (STRUCTOP_STRUCT, $2); }
+                       {
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_structop_operation>
+                           (std::move (arg), copy_name ($2));
+                       }
        ;
 
 primary :      primary '(' arglist ')'
-                       {
-                         write_exp_elt_opcode (OP_FUNCALL);
-                         write_exp_elt_longcst ($3);
-                         write_exp_elt_opcode (OP_FUNCALL);
-                       }
+                       { ada_funcall ($3); }
        |       var_or_type '(' arglist ')'
                        {
                          if ($1 != NULL)
                            {
                              if ($3 != 1)
                                error (_("Invalid conversion"));
-                             write_exp_elt_opcode (UNOP_CAST);
-                             write_exp_elt_type ($1);
-                             write_exp_elt_opcode (UNOP_CAST);
+                             operation_up arg = ada_pop ();
+                             pstate->push_new<unop_cast_operation>
+                               (std::move (arg), $1);
                            }
                          else
-                           {
-                             write_exp_elt_opcode (OP_FUNCALL);
-                             write_exp_elt_longcst ($3);
-                             write_exp_elt_opcode (OP_FUNCALL);
-                           }
+                           ada_funcall ($3);
                        }
        ;
 
-primary :      var_or_type '\'' save_qualifier { type_qualifier = $1; } 
-                  '(' exp ')'
+primary :      var_or_type '\'' '(' exp ')'
                        {
                          if ($1 == NULL)
                            error (_("Type required for qualification"));
-                         write_exp_elt_opcode (UNOP_QUAL);
-                         write_exp_elt_type ($1);
-                         write_exp_elt_opcode (UNOP_QUAL);
-                         type_qualifier = $3;
+                         operation_up arg = ada_pop (true,
+                                                     check_typedef ($1));
+                         pstate->push_new<ada_qual_operation>
+                           (std::move (arg), $1);
                        }
        ;
 
-save_qualifier :       { $$ = type_qualifier; }
-       ;
-
 primary :
                primary '(' simple_exp DOTDOT simple_exp ')'
-                       { write_exp_elt_opcode (TERNOP_SLICE); }
+                       { ada_wrap3<ada_ternop_slice_operation> (); }
        |       var_or_type '(' simple_exp DOTDOT simple_exp ')'
                        { if ($1 == NULL) 
-                            write_exp_elt_opcode (TERNOP_SLICE);
+                           ada_wrap3<ada_ternop_slice_operation> ();
                          else
                            error (_("Cannot slice a type"));
                        }
@@ -311,38 +545,53 @@ primary : '(' exp1 ')'    { }
 
 primary :      var_or_type     %prec VAR
                        { if ($1 != NULL)
-                           {
-                             write_exp_elt_opcode (OP_TYPE);
-                             write_exp_elt_type ($1);
-                             write_exp_elt_opcode (OP_TYPE);
-                           }
+                           pstate->push_new<type_operation> ($1);
                        }
        ;
 
-primary :      SPECIAL_VARIABLE /* Various GDB extensions */
-                       { write_dollar_variable ($1); }
+primary :      DOLLAR_VARIABLE /* Various GDB extensions */
+                       { pstate->push_dollar ($1); }
        ;
 
 primary :      aggregate
-        ;        
+                       {
+                         pstate->push_new<ada_aggregate_operation>
+                           (pop_component ());
+                       }
+       ;        
 
 simple_exp :   primary
        ;
 
 simple_exp :   '-' simple_exp    %prec UNARY
-                       { write_exp_elt_opcode (UNOP_NEG); }
+                       { ada_wrap_overload<ada_neg_operation> (UNOP_NEG); }
        ;
 
 simple_exp :   '+' simple_exp    %prec UNARY
-                       { write_exp_elt_opcode (UNOP_PLUS); }
+                       {
+                         operation_up arg = ada_pop ();
+                         operation_up empty;
+
+                         /* If an overloaded operator was found, use
+                            it.  Otherwise, unary + has no effect and
+                            the argument can be pushed instead.  */
+                         operation_up call = maybe_overload (UNOP_PLUS, arg,
+                                                             empty);
+                         if (call != nullptr)
+                           arg = std::move (call);
+                         pstate->push (std::move (arg));
+                       }
        ;
 
 simple_exp :   NOT simple_exp    %prec UNARY
-                       { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+                       {
+                         ada_wrap_overload<unary_logical_not_operation>
+                           (UNOP_LOGICAL_NOT);
+                       }
        ;
 
 simple_exp :    ABS simple_exp    %prec UNARY
-                       { write_exp_elt_opcode (UNOP_ABS); }
+                       { ada_wrap_overload<ada_abs_operation> (UNOP_ABS); }
        ;
 
 arglist        :               { $$ = 0; }
@@ -363,111 +612,114 @@ primary :       '{' var_or_type '}' primary  %prec '.'
                        { 
                          if ($2 == NULL)
                            error (_("Type required within braces in coercion"));
-                         write_exp_elt_opcode (UNOP_MEMVAL);
-                         write_exp_elt_type ($2);
-                         write_exp_elt_opcode (UNOP_MEMVAL);
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<unop_memval_operation>
+                           (std::move (arg), $2);
                        }
        ;
 
 /* Binary operators in order of decreasing precedence.  */
 
 simple_exp     :       simple_exp STARSTAR simple_exp
-                       { write_exp_elt_opcode (BINOP_EXP); }
+                       { ada_wrap2<ada_binop_exp_operation> (BINOP_EXP); }
        ;
 
 simple_exp     :       simple_exp '*' simple_exp
-                       { write_exp_elt_opcode (BINOP_MUL); }
+                       { ada_wrap2<ada_binop_mul_operation> (BINOP_MUL); }
        ;
 
 simple_exp     :       simple_exp '/' simple_exp
-                       { write_exp_elt_opcode (BINOP_DIV); }
+                       { ada_wrap2<ada_binop_div_operation> (BINOP_DIV); }
        ;
 
 simple_exp     :       simple_exp REM simple_exp /* May need to be fixed to give correct Ada REM */
-                       { write_exp_elt_opcode (BINOP_REM); }
+                       { ada_wrap2<ada_binop_rem_operation> (BINOP_REM); }
        ;
 
 simple_exp     :       simple_exp MOD simple_exp
-                       { write_exp_elt_opcode (BINOP_MOD); }
+                       { ada_wrap2<ada_binop_mod_operation> (BINOP_MOD); }
        ;
 
 simple_exp     :       simple_exp '@' simple_exp       /* GDB extension */
-                       { write_exp_elt_opcode (BINOP_REPEAT); }
+                       { ada_wrap2<repeat_operation> (BINOP_REPEAT); }
        ;
 
 simple_exp     :       simple_exp '+' simple_exp
-                       { write_exp_elt_opcode (BINOP_ADD); }
+                       { ada_wrap_op<ada_binop_addsub_operation> (BINOP_ADD); }
        ;
 
 simple_exp     :       simple_exp '&' simple_exp
-                       { write_exp_elt_opcode (BINOP_CONCAT); }
+                       { ada_wrap2<concat_operation> (BINOP_CONCAT); }
        ;
 
 simple_exp     :       simple_exp '-' simple_exp
-                       { write_exp_elt_opcode (BINOP_SUB); }
+                       { ada_wrap_op<ada_binop_addsub_operation> (BINOP_SUB); }
        ;
 
 relation :     simple_exp
        ;
 
 relation :     simple_exp '=' simple_exp
-                       { write_exp_elt_opcode (BINOP_EQUAL); }
+                       { ada_wrap_op<ada_binop_equal_operation> (BINOP_EQUAL); }
        ;
 
 relation :     simple_exp NOTEQUAL simple_exp
-                       { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+                       { ada_wrap_op<ada_binop_equal_operation> (BINOP_NOTEQUAL); }
        ;
 
 relation :     simple_exp LEQ simple_exp
-                       { write_exp_elt_opcode (BINOP_LEQ); }
+                       { ada_un_wrap2<leq_operation> (BINOP_LEQ); }
        ;
 
 relation :     simple_exp IN simple_exp DOTDOT simple_exp
-                       { write_exp_elt_opcode (TERNOP_IN_RANGE); }
-        |       simple_exp IN primary TICK_RANGE tick_arglist
-                       { write_exp_elt_opcode (BINOP_IN_BOUNDS);
-                         write_exp_elt_longcst ((LONGEST) $5);
-                         write_exp_elt_opcode (BINOP_IN_BOUNDS);
+                       { ada_wrap3<ada_ternop_range_operation> (); }
+       |       simple_exp IN primary TICK_RANGE tick_arglist
+                       {
+                         operation_up rhs = ada_pop ();
+                         operation_up lhs = ada_pop ();
+                         pstate->push_new<ada_binop_in_bounds_operation>
+                           (std::move (lhs), std::move (rhs), $5);
                        }
        |       simple_exp IN var_or_type       %prec TICK_ACCESS
                        { 
                          if ($3 == NULL)
                            error (_("Right operand of 'in' must be type"));
-                         write_exp_elt_opcode (UNOP_IN_RANGE);
-                         write_exp_elt_type ($3);
-                         write_exp_elt_opcode (UNOP_IN_RANGE);
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_unop_range_operation>
+                           (std::move (arg), $3);
                        }
        |       simple_exp NOT IN simple_exp DOTDOT simple_exp
-                       { write_exp_elt_opcode (TERNOP_IN_RANGE);
-                         write_exp_elt_opcode (UNOP_LOGICAL_NOT);
-                       }
-        |       simple_exp NOT IN primary TICK_RANGE tick_arglist
-                       { write_exp_elt_opcode (BINOP_IN_BOUNDS);
-                         write_exp_elt_longcst ((LONGEST) $6);
-                         write_exp_elt_opcode (BINOP_IN_BOUNDS);
-                         write_exp_elt_opcode (UNOP_LOGICAL_NOT);
+                       { ada_wrap3<ada_ternop_range_operation> ();
+                         ada_wrap<unary_logical_not_operation> (); }
+       |       simple_exp NOT IN primary TICK_RANGE tick_arglist
+                       {
+                         operation_up rhs = ada_pop ();
+                         operation_up lhs = ada_pop ();
+                         pstate->push_new<ada_binop_in_bounds_operation>
+                           (std::move (lhs), std::move (rhs), $6);
+                         ada_wrap<unary_logical_not_operation> ();
                        }
        |       simple_exp NOT IN var_or_type   %prec TICK_ACCESS
                        { 
                          if ($4 == NULL)
                            error (_("Right operand of 'in' must be type"));
-                         write_exp_elt_opcode (UNOP_IN_RANGE);
-                         write_exp_elt_type ($4);
-                         write_exp_elt_opcode (UNOP_IN_RANGE);
-                         write_exp_elt_opcode (UNOP_LOGICAL_NOT);
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_unop_range_operation>
+                           (std::move (arg), $4);
+                         ada_wrap<unary_logical_not_operation> ();
                        }
        ;
 
 relation :     simple_exp GEQ simple_exp
-                       { write_exp_elt_opcode (BINOP_GEQ); }
+                       { ada_un_wrap2<geq_operation> (BINOP_GEQ); }
        ;
 
 relation :     simple_exp '<' simple_exp
-                       { write_exp_elt_opcode (BINOP_LESS); }
+                       { ada_un_wrap2<less_operation> (BINOP_LESS); }
        ;
 
 relation :     simple_exp '>' simple_exp
-                       { write_exp_elt_opcode (BINOP_GTR); }
+                       { ada_un_wrap2<gtr_operation> (BINOP_GTR); }
        ;
 
 exp    :       relation
@@ -480,37 +732,45 @@ exp       :       relation
 
 and_exp :
                relation _AND_ relation 
-                       { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+                       { ada_wrap2<ada_bitwise_and_operation>
+                           (BINOP_BITWISE_AND); }
        |       and_exp _AND_ relation
-                       { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+                       { ada_wrap2<ada_bitwise_and_operation>
+                           (BINOP_BITWISE_AND); }
        ;
 
 and_then_exp :
               relation _AND_ THEN relation
-                       { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+                       { ada_wrap2<logical_and_operation>
+                           (BINOP_LOGICAL_AND); }
        |       and_then_exp _AND_ THEN relation
-                       { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
-        ;
+                       { ada_wrap2<logical_and_operation>
+                           (BINOP_LOGICAL_AND); }
+       ;
 
 or_exp :
                relation OR relation 
-                       { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+                       { ada_wrap2<ada_bitwise_ior_operation>
+                           (BINOP_BITWISE_IOR); }
        |       or_exp OR relation
-                       { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+                       { ada_wrap2<ada_bitwise_ior_operation>
+                           (BINOP_BITWISE_IOR); }
        ;
 
 or_else_exp :
               relation OR ELSE relation
-                       { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+                       { ada_wrap2<logical_or_operation> (BINOP_LOGICAL_OR); }
        |      or_else_exp OR ELSE relation
-                       { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
-        ;
+                       { ada_wrap2<logical_or_operation> (BINOP_LOGICAL_OR); }
+       ;
 
 xor_exp :       relation XOR relation
-                       { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+                       { ada_wrap2<ada_bitwise_xor_operation>
+                           (BINOP_BITWISE_XOR); }
        |       xor_exp XOR relation
-                       { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
-        ;
+                       { ada_wrap2<ada_bitwise_xor_operation>
+                           (BINOP_BITWISE_XOR); }
+       ;
 
 /* Primaries can denote types (OP_TYPE).  In cases such as 
    primary TICK_ADDRESS, where a type would be invalid, it will be
@@ -521,36 +781,51 @@ xor_exp :       relation XOR relation
    aType'access evaluates to a type that evaluate_subexp attempts to 
    evaluate. */
 primary :      primary TICK_ACCESS
-                       { write_exp_elt_opcode (UNOP_ADDR); }
+                       { ada_addrof (); }
        |       primary TICK_ADDRESS
-                       { write_exp_elt_opcode (UNOP_ADDR);
-                         write_exp_elt_opcode (UNOP_CAST);
-                         write_exp_elt_type (type_system_address ());
-                         write_exp_elt_opcode (UNOP_CAST);
-                       }
+                       { ada_addrof (type_system_address (pstate)); }
        |       primary TICK_FIRST tick_arglist
-                       { write_int ($3, type_int ());
-                         write_exp_elt_opcode (OP_ATR_FIRST); }
+                       {
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_unop_atr_operation>
+                           (std::move (arg), OP_ATR_FIRST, $3);
+                       }
        |       primary TICK_LAST tick_arglist
-                       { write_int ($3, type_int ());
-                         write_exp_elt_opcode (OP_ATR_LAST); }
+                       {
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_unop_atr_operation>
+                           (std::move (arg), OP_ATR_LAST, $3);
+                       }
        |       primary TICK_LENGTH tick_arglist
-                       { write_int ($3, type_int ());
-                         write_exp_elt_opcode (OP_ATR_LENGTH); }
-        |       primary TICK_SIZE
-                       { write_exp_elt_opcode (OP_ATR_SIZE); }
+                       {
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_unop_atr_operation>
+                           (std::move (arg), OP_ATR_LENGTH, $3);
+                       }
+       |       primary TICK_SIZE
+                       { ada_wrap<ada_atr_size_operation> (); }
        |       primary TICK_TAG
-                       { write_exp_elt_opcode (OP_ATR_TAG); }
-        |       opt_type_prefix TICK_MIN '(' exp ',' exp ')'
-                       { write_exp_elt_opcode (OP_ATR_MIN); }
-        |       opt_type_prefix TICK_MAX '(' exp ',' exp ')'
-                       { write_exp_elt_opcode (OP_ATR_MAX); }
+                       { ada_wrap<ada_atr_tag_operation> (); }
+       |       opt_type_prefix TICK_MIN '(' exp ',' exp ')'
+                       { ada_wrap2<ada_binop_min_operation> (BINOP_MIN); }
+       |       opt_type_prefix TICK_MAX '(' exp ',' exp ')'
+                       { ada_wrap2<ada_binop_max_operation> (BINOP_MAX); }
        |       opt_type_prefix TICK_POS '(' exp ')'
-                       { write_exp_elt_opcode (OP_ATR_POS); }
+                       { ada_wrap<ada_pos_operation> (); }
        |       type_prefix TICK_VAL '(' exp ')'
-                       { write_exp_elt_opcode (OP_ATR_VAL); }
+                       {
+                         operation_up arg = ada_pop ();
+                         pstate->push_new<ada_atr_val_operation>
+                           ($1, std::move (arg));
+                       }
        |       type_prefix TICK_MODULUS
-                       { write_exp_elt_opcode (OP_ATR_MODULUS); }
+                       {
+                         struct type *type_arg = check_typedef ($1);
+                         if (!ada_is_modular_type (type_arg))
+                           error (_("'modulus must be applied to modular type"));
+                         write_int (pstate, ada_modulus (type_arg),
+                                    TYPE_TARGET_TYPE (type_arg));
+                       }
        ;
 
 tick_arglist :                 %prec '('
@@ -560,57 +835,62 @@ tick_arglist :                    %prec '('
        ;
 
 type_prefix :
-                var_or_type
+               var_or_type
                        { 
                          if ($1 == NULL)
                            error (_("Prefix must be type"));
-                         write_exp_elt_opcode (OP_TYPE);
-                         write_exp_elt_type ($1);
-                         write_exp_elt_opcode (OP_TYPE); }
+                         $$ = $1;
+                       }
        ;
 
 opt_type_prefix :
                type_prefix
+                       { $$ = $1; }
        |       /* EMPTY */
-                       { write_exp_elt_opcode (OP_TYPE);
-                         write_exp_elt_type (parse_type->builtin_void);
-                         write_exp_elt_opcode (OP_TYPE); }
+                       { $$ = parse_type (pstate)->builtin_void; }
        ;
 
 
 primary        :       INT
-                       { write_int ((LONGEST) $1.val, $1.type); }
+                       { write_int (pstate, (LONGEST) $1.val, $1.type); }
        ;
 
 primary        :       CHARLIT
-                  { write_int (convert_char_literal (type_qualifier, $1.val),
-                              (type_qualifier == NULL) 
-                              ? $1.type : type_qualifier);
-                 }
+                       {
+                         pstate->push_new<ada_char_operation> ($1.type, $1.val);
+                       }
        ;
 
 primary        :       FLOAT
-                       { write_exp_elt_opcode (OP_DOUBLE);
-                         write_exp_elt_type ($1.type);
-                         write_exp_elt_dblcst ($1.dval);
-                         write_exp_elt_opcode (OP_DOUBLE);
+                       {
+                         float_data data;
+                         std::copy (std::begin ($1.val), std::end ($1.val),
+                                    std::begin (data));
+                         pstate->push_new<float_const_operation>
+                           ($1.type, data);
+                         ada_wrap<ada_wrapped_operation> ();
                        }
        ;
 
 primary        :       NULL_PTR
-                       { write_int (0, type_int ()); }
+                       {
+                         struct type *null_ptr_type
+                           = lookup_pointer_type (parse_type (pstate)->builtin_int0);
+                         write_int (pstate, 0, null_ptr_type);
+                       }
        ;
 
 primary        :       STRING
                        { 
-                         write_exp_op_with_string (OP_STRING, $1);
+                         pstate->push_new<ada_string_operation>
+                           (copy_name ($1));
                        }
        ;
 
 primary :      TRUEKEYWORD
-                       { write_int (1, type_boolean ()); }
-        |      FALSEKEYWORD
-                       { write_int (0, type_boolean ()); }
+                       { write_int (pstate, 1, type_boolean (pstate)); }
+             FALSEKEYWORD
+                       { write_int (pstate, 0, type_boolean (pstate)); }
        ;
 
 primary        :       NEW NAME
@@ -618,22 +898,22 @@ primary   :       NEW NAME
        ;
 
 var_or_type:   NAME        %prec VAR
-                               { $$ = write_var_or_type (NULL, $1); } 
+                               { $$ = write_var_or_type (pstate, NULL, $1); }
        |       block NAME  %prec VAR
-                                { $$ = write_var_or_type ($1, $2); }
+                               { $$ = write_var_or_type (pstate, $1, $2); }
        |       NAME TICK_ACCESS 
                        { 
-                         $$ = write_var_or_type (NULL, $1);
+                         $$ = write_var_or_type (pstate, NULL, $1);
                          if ($$ == NULL)
-                           write_exp_elt_opcode (UNOP_ADDR);
+                           ada_addrof ();
                          else
                            $$ = lookup_pointer_type ($$);
                        }
        |       block NAME TICK_ACCESS
                        { 
-                         $$ = write_var_or_type ($1, $2);
+                         $$ = write_var_or_type (pstate, $1, $2);
                          if ($$ == NULL)
-                           write_exp_elt_opcode (UNOP_ADDR);
+                           ada_addrof ();
                          else
                            $$ = lookup_pointer_type ($$);
                        }
@@ -649,18 +929,20 @@ block   :       NAME COLONCOLON
 aggregate :
                '(' aggregate_component_list ')'  
                        {
-                         write_exp_elt_opcode (OP_AGGREGATE);
-                         write_exp_elt_longcst ($2);
-                         write_exp_elt_opcode (OP_AGGREGATE);
-                       }
+                         std::vector<ada_component_up> components
+                           = pop_components ($2);
+
+                         push_component<ada_aggregate_component>
+                           (std::move (components));
+                       }
        ;
 
 aggregate_component_list :
                component_groups         { $$ = $1; }
        |       positional_list exp
-                       { write_exp_elt_opcode (OP_POSITIONAL);
-                         write_exp_elt_longcst ($1);
-                         write_exp_elt_opcode (OP_POSITIONAL);
+                       {
+                         push_component<ada_positional_component>
+                           ($1, ada_pop ());
                          $$ = $1 + 1;
                        }
        |       positional_list component_groups
@@ -669,15 +951,15 @@ aggregate_component_list :
 
 positional_list :
                exp ','
-                       { write_exp_elt_opcode (OP_POSITIONAL);
-                         write_exp_elt_longcst (0);
-                         write_exp_elt_opcode (OP_POSITIONAL);
+                       {
+                         push_component<ada_positional_component>
+                           (0, ada_pop ());
                          $$ = 1;
                        } 
        |       positional_list exp ','
-                       { write_exp_elt_opcode (OP_POSITIONAL);
-                         write_exp_elt_longcst ($1);
-                         write_exp_elt_opcode (OP_POSITIONAL);
+                       {
+                         push_component<ada_positional_component>
+                           ($1, ada_pop ());
                          $$ = $1 + 1; 
                        }
        ;
@@ -690,16 +972,17 @@ component_groups:
        ;
 
 others         :       OTHERS ARROW exp
-                       { write_exp_elt_opcode (OP_OTHERS); }
+                       {
+                         push_component<ada_others_component> (ada_pop ());
+                       }
        ;
 
 component_group :
                component_associations
                        {
-                         write_exp_elt_opcode (OP_CHOICES);
-                         write_exp_elt_longcst ($1);
-                         write_exp_elt_opcode (OP_CHOICES);
-                       }
+                         ada_choices_component *choices = choice_component ();
+                         choices->set_associations (pop_associations ($1));
+                       }
        ;
 
 /* We use this somewhat obscure definition in order to handle NAME => and
@@ -708,35 +991,60 @@ component_group :
    decisions until after the => or '|', we convert the ambiguity to a 
    resolved shift/reduce conflict. */
 component_associations :
-               NAME ARROW 
-                       { write_name_assoc ($1); }
-                   exp { $$ = 1; }
+               NAME ARROW exp
+                       {
+                         push_component<ada_choices_component> (ada_pop ());
+                         write_name_assoc (pstate, $1);
+                         $$ = 1;
+                       }
        |       simple_exp ARROW exp
-                       { $$ = 1; }
-       |       simple_exp DOTDOT simple_exp ARROW 
-                       { write_exp_elt_opcode (OP_DISCRETE_RANGE);
-                         write_exp_op_with_string (OP_NAME, empty_stoken);
+                       {
+                         push_component<ada_choices_component> (ada_pop ());
+                         push_association<ada_name_association> (ada_pop ());
+                         $$ = 1;
+                       }
+       |       simple_exp DOTDOT simple_exp ARROW exp
+                       {
+                         push_component<ada_choices_component> (ada_pop ());
+                         operation_up rhs = ada_pop ();
+                         operation_up lhs = ada_pop ();
+                         push_association<ada_discrete_range_association>
+                           (std::move (lhs), std::move (rhs));
+                         $$ = 1;
+                       }
+       |       NAME '|' component_associations
+                       {
+                         write_name_assoc (pstate, $1);
+                         $$ = $3 + 1;
+                       }
+       |       simple_exp '|' component_associations
+                       {
+                         push_association<ada_name_association> (ada_pop ());
+                         $$ = $3 + 1;
+                       }
+       |       simple_exp DOTDOT simple_exp '|' component_associations
+
+                       {
+                         operation_up rhs = ada_pop ();
+                         operation_up lhs = ada_pop ();
+                         push_association<ada_discrete_range_association>
+                           (std::move (lhs), std::move (rhs));
+                         $$ = $5 + 1;
                        }
-                   exp { $$ = 1; }
-       |       NAME '|' 
-                       { write_name_assoc ($1); }
-                   component_associations  { $$ = $4 + 1; }
-       |       simple_exp '|'  
-                   component_associations  { $$ = $3 + 1; }
-       |       simple_exp DOTDOT simple_exp '|'
-                       { write_exp_elt_opcode (OP_DISCRETE_RANGE); }
-                   component_associations  { $$ = $6 + 1; }
        ;
 
 /* Some extensions borrowed from C, for the benefit of those who find they
    can't get used to Ada notation in GDB.  */
 
 primary        :       '*' primary             %prec '.'
-                       { write_exp_elt_opcode (UNOP_IND); }
+                       { ada_wrap<ada_unop_ind_operation> (); }
        |       '&' primary             %prec '.'
-                       { write_exp_elt_opcode (UNOP_ADDR); }
+                       { ada_addrof (); }
        |       primary '[' exp ']'
-                       { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+                       {
+                         ada_wrap2<subscript_operation> (BINOP_SUBSCRIPT);
+                         ada_wrap<ada_wrapped_operation> ();
+                       }
        ;
 
 %%
@@ -757,7 +1065,6 @@ primary    :       '*' primary             %prec '.'
 #define yy_switch_to_buffer ada_yy_switch_to_buffer
 #define yyrestart ada_yyrestart
 #define yytext ada_yytext
-#define yywrap ada_yywrap
 
 static struct obstack temp_parse_space;
 
@@ -767,110 +1074,77 @@ static struct obstack temp_parse_space;
 #include "ada-lex.c"
 
 int
-ada_parse (void)
+ada_parse (struct parser_state *par_state)
 {
+  /* Setting up the parser state.  */
+  scoped_restore pstate_restore = make_scoped_restore (&pstate);
+  gdb_assert (par_state != NULL);
+  pstate = par_state;
+
   lexer_init (yyin);           /* (Re-)initialize lexer.  */
-  type_qualifier = NULL;
   obstack_free (&temp_parse_space, NULL);
   obstack_init (&temp_parse_space);
+  components.clear ();
+  associations.clear ();
 
-  return _ada_parse ();
-}
-
-void
-yyerror (char *msg)
-{
-  error (_("Error in expression, near `%s'."), lexptr);
+  int result = yyparse ();
+  if (!result)
+    {
+      struct type *context_type = nullptr;
+      if (par_state->void_context_p)
+       context_type = parse_type (par_state)->builtin_void;
+      pstate->set_operation (ada_pop (true, context_type));
+    }
+  return result;
 }
 
-/* The operator name corresponding to operator symbol STRING (adds
-   quotes and maps to lower-case).  Destroys the previous contents of
-   the array pointed to by STRING.ptr.  Error if STRING does not match
-   a valid Ada operator.  Assumes that STRING.ptr points to a
-   null-terminated string and that, if STRING is a valid operator
-   symbol, the array pointed to by STRING.ptr contains at least
-   STRING.length+3 characters.  */
-
-static struct stoken
-string_to_operator (struct stoken string)
+static void
+yyerror (const char *msg)
 {
-  int i;
-
-  for (i = 0; ada_opname_table[i].encoded != NULL; i += 1)
-    {
-      if (string.length == strlen (ada_opname_table[i].decoded)-2
-         && strncasecmp (string.ptr, ada_opname_table[i].decoded+1,
-                         string.length) == 0)
-       {
-         strncpy (string.ptr, ada_opname_table[i].decoded,
-                  string.length+2);
-         string.length += 2;
-         return string;
-       }
-    }
-  error (_("Invalid operator symbol `%s'"), string.ptr);
+  error (_("Error in expression, near `%s'."), pstate->lexptr);
 }
 
 /* Emit expression to access an instance of SYM, in block BLOCK (if
- * non-NULL), and with :: qualification ORIG_LEFT_CONTEXT.  */
+   non-NULL).  */
+
 static void
-write_var_from_sym (struct block *orig_left_context,
-                   struct block *block,
-                   struct symbol *sym)
+write_var_from_sym (struct parser_state *par_state, block_symbol sym)
 {
-  if (orig_left_context == NULL && symbol_read_needs_frame (sym))
-    {
-      if (innermost_block == 0
-         || contained_in (block, innermost_block))
-       innermost_block = block;
-    }
+  if (symbol_read_needs_frame (sym.symbol))
+    par_state->block_tracker->update (sym.block, INNERMOST_BLOCK_FOR_SYMBOLS);
 
-  write_exp_elt_opcode (OP_VAR_VALUE);
-  write_exp_elt_block (block);
-  write_exp_elt_sym (sym);
-  write_exp_elt_opcode (OP_VAR_VALUE);
+  par_state->push_new<ada_var_value_operation> (sym);
 }
 
 /* Write integer or boolean constant ARG of type TYPE.  */
 
 static void
-write_int (LONGEST arg, struct type *type)
+write_int (struct parser_state *par_state, LONGEST arg, struct type *type)
 {
-  write_exp_elt_opcode (OP_LONG);
-  write_exp_elt_type (type);
-  write_exp_elt_longcst (arg);
-  write_exp_elt_opcode (OP_LONG);
+  pstate->push_new<long_const_operation> (type, arg);
+  ada_wrap<ada_wrapped_operation> ();
 }
 
-/* Write an OPCODE, string, OPCODE sequence to the current expression.  */
-static void
-write_exp_op_with_string (enum exp_opcode opcode, struct stoken token)
-{
-  write_exp_elt_opcode (opcode);
-  write_exp_string (token);
-  write_exp_elt_opcode (opcode);
-}
-  
 /* Emit expression corresponding to the renamed object named 
* designated by RENAMED_ENTITY[0 .. RENAMED_ENTITY_LEN-1] in the
* context of ORIG_LEFT_CONTEXT, to which is applied the operations
* encoded by RENAMING_EXPR.  MAX_DEPTH is the maximum number of
* cascaded renamings to allow.  If ORIG_LEFT_CONTEXT is null, it
* defaults to the currently selected block. ORIG_SYMBOL is the 
* symbol that originally encoded the renaming.  It is needed only
* because its prefix also qualifies any index variables used to index
* or slice an array.  It should not be necessary once we go to the
* new encoding entirely (FIXME pnh 7/20/2007).  */
  designated by RENAMED_ENTITY[0 .. RENAMED_ENTITY_LEN-1] in the
  context of ORIG_LEFT_CONTEXT, to which is applied the operations
  encoded by RENAMING_EXPR.  MAX_DEPTH is the maximum number of
  cascaded renamings to allow.  If ORIG_LEFT_CONTEXT is null, it
  defaults to the currently selected block. ORIG_SYMBOL is the 
  symbol that originally encoded the renaming.  It is needed only
  because its prefix also qualifies any index variables used to index
  or slice an array.  It should not be necessary once we go to the
  new encoding entirely (FIXME pnh 7/20/2007).  */
 
 static void
-write_object_renaming (struct block *orig_left_context,
+write_object_renaming (struct parser_state *par_state,
+                      const struct block *orig_left_context,
                       const char *renamed_entity, int renamed_entity_len,
                       const char *renaming_expr, int max_depth)
 {
   char *name;
   enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
-  struct symbol *sym;
-  struct block *block;
+  struct block_symbol sym_info;
 
   if (max_depth <= 0)
     error (_("Could not find renamed symbol"));
@@ -878,30 +1152,30 @@ write_object_renaming (struct block *orig_left_context,
   if (orig_left_context == NULL)
     orig_left_context = get_selected_block (NULL);
 
-  name = obsavestring (renamed_entity, renamed_entity_len, &temp_parse_space);
-  sym = ada_lookup_encoded_symbol (name, orig_left_context, VAR_DOMAIN, 
-                                  &block);
-  if (sym == NULL)
-    error (_("Could not find renamed variable: %s"), ada_decode (name));
-  else if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+  name = obstack_strndup (&temp_parse_space, renamed_entity,
+                         renamed_entity_len);
+  ada_lookup_encoded_symbol (name, orig_left_context, VAR_DOMAIN, &sym_info);
+  if (sym_info.symbol == NULL)
+    error (_("Could not find renamed variable: %s"), ada_decode (name).c_str ());
+  else if (SYMBOL_CLASS (sym_info.symbol) == LOC_TYPEDEF)
     /* We have a renaming of an old-style renaming symbol.  Don't
        trust the block information.  */
-    block = orig_left_context;
+    sym_info.block = orig_left_context;
 
   {
     const char *inner_renamed_entity;
     int inner_renamed_entity_len;
     const char *inner_renaming_expr;
 
-    switch (ada_parse_renaming (sym, &inner_renamed_entity, 
+    switch (ada_parse_renaming (sym_info.symbol, &inner_renamed_entity,
                                &inner_renamed_entity_len,
                                &inner_renaming_expr))
       {
       case ADA_NOT_RENAMING:
-       write_var_from_sym (orig_left_context, block, sym);
+       write_var_from_sym (par_state, sym_info);
        break;
       case ADA_OBJECT_RENAMING:
-       write_object_renaming (block,
+       write_object_renaming (par_state, sym_info.block,
                               inner_renamed_entity, inner_renamed_entity_len,
                               inner_renaming_expr, max_depth - 1);
        break;
@@ -917,11 +1191,12 @@ write_object_renaming (struct block *orig_left_context,
 
       switch (*renaming_expr) {
       case 'A':
-        renaming_expr += 1;
-        write_exp_elt_opcode (UNOP_IND);
-        break;
+       renaming_expr += 1;
+       ada_wrap<ada_unop_ind_operation> ();
+       break;
       case 'L':
        slice_state = LOWER_BOUND;
+       /* FALLTHROUGH */
       case 'S':
        renaming_expr += 1;
        if (isdigit (*renaming_expr))
@@ -931,54 +1206,46 @@ write_object_renaming (struct block *orig_left_context,
            if (next == renaming_expr)
              goto BadEncoding;
            renaming_expr = next;
-           write_exp_elt_opcode (OP_LONG);
-           write_exp_elt_type (type_int ());
-           write_exp_elt_longcst ((LONGEST) val);
-           write_exp_elt_opcode (OP_LONG);
+           write_int (par_state, val, type_int (par_state));
          }
        else
          {
            const char *end;
            char *index_name;
-           struct symbol *index_sym;
+           struct block_symbol index_sym_info;
 
            end = strchr (renaming_expr, 'X');
            if (end == NULL)
              end = renaming_expr + strlen (renaming_expr);
 
-           index_name =
-             obsavestring (renaming_expr, end - renaming_expr,
-                           &temp_parse_space);
+           index_name = obstack_strndup (&temp_parse_space, renaming_expr,
+                                         end - renaming_expr);
            renaming_expr = end;
 
-           index_sym = ada_lookup_encoded_symbol (index_name, NULL,
-                                                  VAR_DOMAIN, &block);
-           if (index_sym == NULL)
+           ada_lookup_encoded_symbol (index_name, orig_left_context,
+                                      VAR_DOMAIN, &index_sym_info);
+           if (index_sym_info.symbol == NULL)
              error (_("Could not find %s"), index_name);
-           else if (SYMBOL_CLASS (index_sym) == LOC_TYPEDEF)
+           else if (SYMBOL_CLASS (index_sym_info.symbol) == LOC_TYPEDEF)
              /* Index is an old-style renaming symbol.  */
-             block = orig_left_context;
-           write_var_from_sym (NULL, block, index_sym);
+             index_sym_info.block = orig_left_context;
+           write_var_from_sym (par_state, index_sym_info);
          }
        if (slice_state == SIMPLE_INDEX)
-         {
-           write_exp_elt_opcode (OP_FUNCALL);
-           write_exp_elt_longcst ((LONGEST) 1);
-           write_exp_elt_opcode (OP_FUNCALL);
-         }
+         ada_funcall (1);
        else if (slice_state == LOWER_BOUND)
          slice_state = UPPER_BOUND;
        else if (slice_state == UPPER_BOUND)
          {
-           write_exp_elt_opcode (TERNOP_SLICE);
+           ada_wrap3<ada_ternop_slice_operation> ();
            slice_state = SIMPLE_INDEX;
          }
        break;
 
       case 'R':
        {
-         struct stoken field_name;
          const char *end;
+
          renaming_expr += 1;
 
          if (slice_state != SIMPLE_INDEX)
@@ -986,12 +1253,12 @@ write_object_renaming (struct block *orig_left_context,
          end = strchr (renaming_expr, 'X');
          if (end == NULL)
            end = renaming_expr + strlen (renaming_expr);
-         field_name.length = end - renaming_expr;
-         field_name.ptr = malloc (end - renaming_expr + 1);
-         strncpy (field_name.ptr, renaming_expr, end - renaming_expr);
-         field_name.ptr[end - renaming_expr] = '\000';
+
+         operation_up arg = ada_pop ();
+         pstate->push_new<ada_structop_operation>
+           (std::move (arg), std::string (renaming_expr,
+                                          end - renaming_expr));
          renaming_expr = end;
-         write_exp_op_with_string (STRUCTOP_STRUCT, field_name);
          break;
        }
 
@@ -1006,32 +1273,37 @@ write_object_renaming (struct block *orig_left_context,
   error (_("Internal error in encoding of renaming declaration"));
 }
 
-static struct block*
-block_lookup (struct block *context, char *raw_name)
+static const struct block*
+block_lookup (const struct block *context, const char *raw_name)
 {
-  char *name;
-  struct ada_symbol_info *syms;
-  int nsyms;
+  const char *name;
   struct symtab *symtab;
+  const struct block *result = NULL;
 
+  std::string name_storage;
   if (raw_name[0] == '\'')
     {
       raw_name += 1;
       name = raw_name;
     }
   else
-    name = ada_encode (raw_name);
+    {
+      name_storage = ada_encode (raw_name);
+      name = name_storage.c_str ();
+    }
+
+  std::vector<struct block_symbol> syms
+    = ada_lookup_symbol_list (name, context, VAR_DOMAIN);
 
-  nsyms = ada_lookup_symbol_list (name, context, VAR_DOMAIN, &syms);
-  if (context == NULL &&
-      (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK))
+  if (context == NULL
+      && (syms.empty () || SYMBOL_CLASS (syms[0].symbol) != LOC_BLOCK))
     symtab = lookup_symtab (name);
   else
     symtab = NULL;
 
   if (symtab != NULL)
-    return BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
-  else if (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK)
+    result = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
+  else if (syms.empty () || SYMBOL_CLASS (syms[0].symbol) != LOC_BLOCK)
     {
       if (context == NULL)
        error (_("No file or function \"%s\"."), raw_name);
@@ -1040,28 +1312,30 @@ block_lookup (struct block *context, char *raw_name)
     }
   else
     {
-      if (nsyms > 1)
+      if (syms.size () > 1)
        warning (_("Function name \"%s\" ambiguous here"), raw_name);
-      return SYMBOL_BLOCK_VALUE (syms[0].sym);
+      result = SYMBOL_BLOCK_VALUE (syms[0].symbol);
     }
+
+  return result;
 }
 
 static struct symbol*
-select_possible_type_sym (struct ada_symbol_info *syms, int nsyms)
+select_possible_type_sym (const std::vector<struct block_symbol> &syms)
 {
   int i;
   int preferred_index;
   struct type *preferred_type;
          
   preferred_index = -1; preferred_type = NULL;
-  for (i = 0; i < nsyms; i += 1)
-    switch (SYMBOL_CLASS (syms[i].sym))
+  for (i = 0; i < syms.size (); i += 1)
+    switch (SYMBOL_CLASS (syms[i].symbol))
       {
       case LOC_TYPEDEF:
-       if (ada_prefer_type (SYMBOL_TYPE (syms[i].sym), preferred_type))
+       if (ada_prefer_type (SYMBOL_TYPE (syms[i].symbol), preferred_type))
          {
            preferred_index = i;
-           preferred_type = SYMBOL_TYPE (syms[i].sym);
+           preferred_type = SYMBOL_TYPE (syms[i].symbol);
          }
        break;
       case LOC_REGISTER:
@@ -1076,30 +1350,29 @@ select_possible_type_sym (struct ada_symbol_info *syms, int nsyms)
       }
   if (preferred_type == NULL)
     return NULL;
-  return syms[preferred_index].sym;
+  return syms[preferred_index].symbol;
 }
 
 static struct type*
-find_primitive_type (char *name)
+find_primitive_type (struct parser_state *par_state, const char *name)
 {
   struct type *type;
-  type = language_lookup_primitive_type_by_name (parse_language,
-                                                parse_gdbarch,
-                                                name);
+  type = language_lookup_primitive_type (par_state->language (),
+                                        par_state->gdbarch (),
+                                        name);
   if (type == NULL && strcmp ("system__address", name) == 0)
-    type = type_system_address ();
+    type = type_system_address (par_state);
 
   if (type != NULL)
     {
       /* Check to see if we have a regular definition of this
         type that just didn't happen to have been read yet.  */
-      int ntypes;
       struct symbol *sym;
       char *expanded_name = 
        (char *) alloca (strlen (name) + sizeof ("standard__"));
       strcpy (expanded_name, "standard__");
       strcat (expanded_name, name);
-      sym = ada_lookup_symbol (expanded_name, NULL, VAR_DOMAIN, NULL);
+      sym = ada_lookup_symbol (expanded_name, NULL, VAR_DOMAIN).symbol;
       if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
        type = SYMBOL_TYPE (sym);
     }
@@ -1108,7 +1381,7 @@ find_primitive_type (char *name)
 }
 
 static int
-chop_selector (char *name, int end)
+chop_selector (const char *name, int end)
 {
   int i;
   for (i = end - 1; i > 0; i -= 1)
@@ -1121,8 +1394,8 @@ chop_selector (char *name, int end)
    '.'), chop this separator and return the result; else, return
    NAME.  */
 
-static char *
-chop_separator (char *name)
+static const char *
+chop_separator (const char *name)
 {
   if (*name == '.')
    return name + 1;
@@ -1137,19 +1410,18 @@ chop_separator (char *name)
    <sep> is '__' or '.', write the indicated sequence of
    STRUCTOP_STRUCT expression operators. */
 static void
-write_selectors (char *sels)
+write_selectors (struct parser_state *par_state, const char *sels)
 {
   while (*sels != '\0')
     {
-      struct stoken field_name;
-      char *p = chop_separator (sels);
+      const char *p = chop_separator (sels);
       sels = p;
       while (*sels != '\0' && *sels != '.' 
             && (sels[0] != '_' || sels[1] != '_'))
        sels += 1;
-      field_name.length = sels - p;
-      field_name.ptr = p;
-      write_exp_op_with_string (STRUCTOP_STRUCT, field_name);
+      operation_up arg = ada_pop ();
+      pstate->push_new<ada_structop_operation>
+       (std::move (arg), std::string (p, sels - p));
     }
 }
 
@@ -1158,19 +1430,17 @@ write_selectors (char *sels)
    a temporary symbol that is valid until the next call to ada_parse.
    */
 static void
-write_ambiguous_var (struct block *block, char *name, int len)
+write_ambiguous_var (struct parser_state *par_state,
+                    const struct block *block, const char *name, int len)
 {
-  struct symbol *sym =
-    obstack_alloc (&temp_parse_space, sizeof (struct symbol));
-  memset (sym, 0, sizeof (struct symbol));
+  struct symbol *sym = new (&temp_parse_space) symbol ();
+
   SYMBOL_DOMAIN (sym) = UNDEF_DOMAIN;
-  SYMBOL_LINKAGE_NAME (sym) = obsavestring (name, len, &temp_parse_space);
-  SYMBOL_LANGUAGE (sym) = language_ada;
+  sym->set_linkage_name (obstack_strndup (&temp_parse_space, name, len));
+  sym->set_language (language_ada, nullptr);
 
-  write_exp_elt_opcode (OP_VAR_VALUE);
-  write_exp_elt_block (block);
-  write_exp_elt_sym (sym);
-  write_exp_elt_opcode (OP_VAR_VALUE);
+  block_symbol bsym { sym, block };
+  par_state->push_new<ada_var_value_operation> (bsym);
 }
 
 /* A convenient wrapper around ada_get_field_index that takes
@@ -1179,9 +1449,9 @@ write_ambiguous_var (struct block *block, char *name, int len)
 
 static int
 ada_nget_field_index (const struct type *type, const char *field_name0,
-                      int field_name_len, int maybe_missing)
+                     int field_name_len, int maybe_missing)
 {
-  char *field_name = alloca ((field_name_len + 1) * sizeof (char));
+  char *field_name = (char *) alloca ((field_name_len + 1) * sizeof (char));
 
   strncpy (field_name, field_name0, field_name_len);
   field_name[field_name_len] = '\0';
@@ -1200,15 +1470,16 @@ ada_nget_field_index (const struct type *type, const char *field_name0,
    In case of failure, we return NULL.  */
 
 static struct type *
-get_symbol_field_type (struct symbol *sym, char *encoded_field_name)
+get_symbol_field_type (struct symbol *sym, const char *encoded_field_name)
 {
-  char *field_name = encoded_field_name;
-  char *subfield_name;
+  const char *field_name = encoded_field_name;
+  const char *subfield_name;
   struct type *type = SYMBOL_TYPE (sym);
   int fieldno;
 
   if (type == NULL || field_name == NULL)
     return NULL;
+  type = check_typedef (type);
 
   while (field_name[0] != '\0')
     {
@@ -1216,7 +1487,7 @@ get_symbol_field_type (struct symbol *sym, char *encoded_field_name)
 
       fieldno = ada_get_field_index (type, field_name, 1);
       if (fieldno >= 0)
-        return TYPE_FIELD_TYPE (type, fieldno);
+       return type->field (fieldno).type ();
 
       subfield_name = field_name;
       while (*subfield_name != '\0' && *subfield_name != '.' 
@@ -1224,14 +1495,14 @@ get_symbol_field_type (struct symbol *sym, char *encoded_field_name)
        subfield_name += 1;
 
       if (subfield_name[0] == '\0')
-        return NULL;
+       return NULL;
 
       fieldno = ada_nget_field_index (type, field_name,
-                                      subfield_name - field_name, 1);
+                                     subfield_name - field_name, 1);
       if (fieldno < 0)
-        return NULL;
+       return NULL;
 
-      type = TYPE_FIELD_TYPE (type, fieldno);
+      type = type->field (fieldno).type ();
       field_name = subfield_name;
     }
 
@@ -1249,18 +1520,20 @@ get_symbol_field_type (struct symbol *sym, char *encoded_field_name)
    identifier).  */
 
 static struct type*
-write_var_or_type (struct block *block, struct stoken name0)
+write_var_or_type (struct parser_state *par_state,
+                  const struct block *block, struct stoken name0)
 {
   int depth;
   char *encoded_name;
   int name_len;
 
   if (block == NULL)
-    block = expression_context_block;
+    block = par_state->expression_context_block;
 
-  encoded_name = ada_encode (name0.ptr);
-  name_len = strlen (encoded_name);
-  encoded_name = obsavestring (encoded_name, name_len, &temp_parse_space);
+  std::string name_storage = ada_encode (name0.ptr);
+  name_len = name_storage.size ();
+  encoded_name = obstack_strndup (&temp_parse_space, name_storage.c_str (),
+                                 name_len);
   for (depth = 0; depth < MAX_RENAMING_CHAIN_LENGTH; depth += 1)
     {
       int tail_index;
@@ -1268,8 +1541,6 @@ write_var_or_type (struct block *block, struct stoken name0)
       tail_index = name_len;
       while (tail_index > 0)
        {
-         int nsyms;
-         struct ada_symbol_info *syms;
          struct symbol *type_sym;
          struct symbol *renaming_sym;
          const char* renaming;
@@ -1278,30 +1549,16 @@ write_var_or_type (struct block *block, struct stoken name0)
          int terminator = encoded_name[tail_index];
 
          encoded_name[tail_index] = '\0';
-         nsyms = ada_lookup_symbol_list (encoded_name, block,
-                                         VAR_DOMAIN, &syms);
+         std::vector<struct block_symbol> syms
+           = ada_lookup_symbol_list (encoded_name, block, VAR_DOMAIN);
          encoded_name[tail_index] = terminator;
 
-         /* A single symbol may rename a package or object. */
-
-         /* This should go away when we move entirely to new version.
-            FIXME pnh 7/20/2007. */
-         if (nsyms == 1)
-           {
-             struct symbol *renaming =
-               ada_find_renaming_symbol (SYMBOL_LINKAGE_NAME (syms[0].sym), 
-                                         syms[0].block);
-
-             if (renaming != NULL)
-               syms[0].sym = renaming;
-           }
-
-         type_sym = select_possible_type_sym (syms, nsyms);
+         type_sym = select_possible_type_sym (syms);
 
          if (type_sym != NULL)
            renaming_sym = type_sym;
-         else if (nsyms == 1)
-           renaming_sym = syms[0].sym;
+         else if (syms.size () == 1)
+           renaming_sym = syms[0].symbol;
          else 
            renaming_sym = NULL;
 
@@ -1314,9 +1571,9 @@ write_var_or_type (struct block *block, struct stoken name0)
            case ADA_EXCEPTION_RENAMING:
            case ADA_SUBPROGRAM_RENAMING:
              {
+               int alloc_len = renaming_len + name_len - tail_index + 1;
                char *new_name
-                 = obstack_alloc (&temp_parse_space,
-                                  renaming_len + name_len - tail_index + 1);
+                 = (char *) obstack_alloc (&temp_parse_space, alloc_len);
                strncpy (new_name, renaming, renaming_len);
                strcpy (new_name + renaming_len, encoded_name + tail_index);
                encoded_name = new_name;
@@ -1324,9 +1581,9 @@ write_var_or_type (struct block *block, struct stoken name0)
                goto TryAfterRenaming;
              } 
            case ADA_OBJECT_RENAMING:
-             write_object_renaming (block, renaming, renaming_len, 
+             write_object_renaming (par_state, block, renaming, renaming_len,
                                     renaming_expr, MAX_RENAMING_CHAIN_LENGTH);
-             write_selectors (encoded_name + tail_index);
+             write_selectors (par_state, encoded_name + tail_index);
              return NULL;
            default:
              internal_error (__FILE__, __LINE__,
@@ -1335,46 +1592,46 @@ write_var_or_type (struct block *block, struct stoken name0)
 
          if (type_sym != NULL)
            {
-              struct type *field_type;
-              
-              if (tail_index == name_len)
-                return SYMBOL_TYPE (type_sym);
-
-              /* We have some extraneous characters after the type name.
-                 If this is an expression "TYPE_NAME.FIELD0.[...].FIELDN",
-                 then try to get the type of FIELDN.  */
-              field_type
-                = get_symbol_field_type (type_sym, encoded_name + tail_index);
-              if (field_type != NULL)
-                return field_type;
+             struct type *field_type;
+             
+             if (tail_index == name_len)
+               return SYMBOL_TYPE (type_sym);
+
+             /* We have some extraneous characters after the type name.
+                If this is an expression "TYPE_NAME.FIELD0.[...].FIELDN",
+                then try to get the type of FIELDN.  */
+             field_type
+               = get_symbol_field_type (type_sym, encoded_name + tail_index);
+             if (field_type != NULL)
+               return field_type;
              else 
                error (_("Invalid attempt to select from type: \"%s\"."),
-                       name0.ptr);
+                      name0.ptr);
            }
-         else if (tail_index == name_len && nsyms == 0)
+         else if (tail_index == name_len && syms.empty ())
            {
-             struct type *type = find_primitive_type (encoded_name);
+             struct type *type = find_primitive_type (par_state,
+                                                      encoded_name);
 
              if (type != NULL)
                return type;
            }
 
-         if (nsyms == 1)
+         if (syms.size () == 1)
            {
-             write_var_from_sym (block, syms[0].block, syms[0].sym);
-             write_selectors (encoded_name + tail_index);
+             write_var_from_sym (par_state, syms[0]);
+             write_selectors (par_state, encoded_name + tail_index);
              return NULL;
            }
-         else if (nsyms == 0) 
+         else if (syms.empty ())
            {
-             int i;
-             struct minimal_symbol *msym 
+             struct bound_minimal_symbol msym
                = ada_lookup_simple_minsym (encoded_name);
-             if (msym != NULL)
+             if (msym.minsym != NULL)
                {
-                 write_exp_msymbol (msym);
+                 par_state->push_new<ada_var_msym_value_operation> (msym);
                  /* Maybe cause error here rather than later? FIXME? */
-                 write_selectors (encoded_name + tail_index);
+                 write_selectors (par_state, encoded_name + tail_index);
                  return NULL;
                }
 
@@ -1387,15 +1644,16 @@ write_var_or_type (struct block *block, struct stoken name0)
            } 
          else
            {
-             write_ambiguous_var (block, encoded_name, tail_index);
-             write_selectors (encoded_name + tail_index);
+             write_ambiguous_var (par_state, block, encoded_name,
+                                  tail_index);
+             write_selectors (par_state, encoded_name + tail_index);
              return NULL;
            }
        }
 
       if (!have_full_symbols () && !have_partial_symbols () && block == NULL)
        error (_("No symbol table is loaded.  Use the \"file\" command."));
-      if (block == expression_context_block)
+      if (block == par_state->expression_context_block)
        error (_("No definition of \"%s\" in current context."), name0.ptr);
       else
        error (_("No definition of \"%s\" in specified context."), name0.ptr);
@@ -1423,114 +1681,77 @@ write_var_or_type (struct block *block, struct stoken name0)
    ambiguous name, one must write instead ((R) => 42). */
    
 static void
-write_name_assoc (struct stoken name)
+write_name_assoc (struct parser_state *par_state, struct stoken name)
 {
   if (strchr (name.ptr, '.') == NULL)
     {
-      struct ada_symbol_info *syms;
-      int nsyms = ada_lookup_symbol_list (name.ptr, expression_context_block,
-                                         VAR_DOMAIN, &syms);
-      if (nsyms != 1 || SYMBOL_CLASS (syms[0].sym) == LOC_TYPEDEF)
-       write_exp_op_with_string (OP_NAME, name);
+      std::vector<struct block_symbol> syms
+       = ada_lookup_symbol_list (name.ptr,
+                                 par_state->expression_context_block,
+                                 VAR_DOMAIN);
+
+      if (syms.size () != 1 || SYMBOL_CLASS (syms[0].symbol) == LOC_TYPEDEF)
+       pstate->push_new<ada_string_operation> (copy_name (name));
       else
-       write_var_from_sym (NULL, syms[0].block, syms[0].sym);
+       write_var_from_sym (par_state, syms[0]);
     }
   else
-    if (write_var_or_type (NULL, name) != NULL)
+    if (write_var_or_type (par_state, NULL, name) != NULL)
       error (_("Invalid use of type."));
-}
-
-/* Convert the character literal whose ASCII value would be VAL to the
-   appropriate value of type TYPE, if there is a translation.
-   Otherwise return VAL.  Hence, in an enumeration type ('A', 'B'),
-   the literal 'A' (VAL == 65), returns 0.  */
-
-static LONGEST
-convert_char_literal (struct type *type, LONGEST val)
-{
-  char name[7];
-  int f;
 
-  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM)
-    return val;
-  sprintf (name, "QU%02x", (int) val);
-  for (f = 0; f < TYPE_NFIELDS (type); f += 1)
-    {
-      if (strcmp (name, TYPE_FIELD_NAME (type, f)) == 0)
-       return TYPE_FIELD_BITPOS (type, f);
-    }
-  return val;
-}
-
-static struct type *
-type_int (void)
-{
-  return parse_type->builtin_int;
+  push_association<ada_name_association> (ada_pop ());
 }
 
 static struct type *
-type_long (void)
+type_int (struct parser_state *par_state)
 {
-  return parse_type->builtin_long;
+  return parse_type (par_state)->builtin_int;
 }
 
 static struct type *
-type_long_long (void)
+type_long (struct parser_state *par_state)
 {
-  return parse_type->builtin_long_long;
+  return parse_type (par_state)->builtin_long;
 }
 
 static struct type *
-type_float (void)
+type_long_long (struct parser_state *par_state)
 {
-  return parse_type->builtin_float;
+  return parse_type (par_state)->builtin_long_long;
 }
 
 static struct type *
-type_double (void)
+type_long_double (struct parser_state *par_state)
 {
-  return parse_type->builtin_double;
+  return parse_type (par_state)->builtin_long_double;
 }
 
 static struct type *
-type_long_double (void)
+type_char (struct parser_state *par_state)
 {
-  return parse_type->builtin_long_double;
+  return language_string_char_type (par_state->language (),
+                                   par_state->gdbarch ());
 }
 
 static struct type *
-type_char (void)
+type_boolean (struct parser_state *par_state)
 {
-  return language_string_char_type (parse_language, parse_gdbarch);
+  return parse_type (par_state)->builtin_bool;
 }
 
 static struct type *
-type_boolean (void)
-{
-  return parse_type->builtin_bool;
-}
-
-static struct type *
-type_system_address (void)
+type_system_address (struct parser_state *par_state)
 {
   struct type *type 
-    = language_lookup_primitive_type_by_name (parse_language,
-                                             parse_gdbarch,
-                                             "system__address");
-  return  type != NULL ? type : parse_type->builtin_data_ptr;
+    = language_lookup_primitive_type (par_state->language (),
+                                     par_state->gdbarch (),
+                                     "system__address");
+  return  type != NULL ? type : parse_type (par_state)->builtin_data_ptr;
 }
 
+void _initialize_ada_exp ();
 void
-_initialize_ada_exp (void)
+_initialize_ada_exp ()
 {
   obstack_init (&temp_parse_space);
 }
-
-/* FIXME: hilfingr/2004-10-05: Hack to remove warning.  The function
-   string_to_operator is supposed to be used for cases where one
-   calls an operator function with prefix notation, as in 
-   "+" (a, b), but at some point, this code seems to have gone
-   missing. */
-
-struct stoken (*dummy_string_to_ada_operator) (struct stoken) 
-     = string_to_operator;