/* YACC parser for D expressions, for GDB.
- Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ Copyright (C) 2014-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
#include "charset.h"
#include "block.h"
+#include "type-stack.h"
+#include "expop.h"
-#define parse_type(ps) builtin_type (parse_gdbarch (ps))
-#define parse_d_type(ps) builtin_d_type (parse_gdbarch (ps))
-
-/* 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. Note that 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. */
-
-#define yymaxdepth d_maxdepth
-#define yyparse d_parse_internal
-#define yylex d_lex
-#define yyerror d_error
-#define yylval d_lval
-#define yychar d_char
-#define yydebug d_debug
-#define yypact d_pact
-#define yyr1 d_r1
-#define yyr2 d_r2
-#define yydef d_def
-#define yychk d_chk
-#define yypgo d_pgo
-#define yyact d_act
-#define yyexca d_exca
-#define yyerrflag d_errflag
-#define yynerrs d_nerrs
-#define yyps d_ps
-#define yypv d_pv
-#define yys d_s
-#define yy_yys d_yys
-#define yystate d_state
-#define yytmp d_tmp
-#define yyv d_v
-#define yy_yyv d_yyv
-#define yyval d_val
-#define yylloc d_lloc
-#define yyreds d_reds /* With YYDEBUG defined */
-#define yytoks d_toks /* With YYDEBUG defined */
-#define yyname d_name /* With YYDEBUG defined */
-#define yyrule d_rule /* With YYDEBUG defined */
-#define yylhs d_yylhs
-#define yylen d_yylen
-#define yydefre d_yydefred
-#define yydgoto d_yydgoto
-#define yysindex d_yysindex
-#define yyrindex d_yyrindex
-#define yygindex d_yygindex
-#define yytable d_yytable
-#define yycheck d_yycheck
-#define yyss d_yyss
-#define yysslim d_yysslim
-#define yyssp d_yyssp
-#define yystacksize d_yystacksize
-#define yyvs d_yyvs
-#define yyvsp d_yyvsp
-
-#ifndef YYDEBUG
-#define YYDEBUG 1 /* Default to yydebug support */
-#endif
-
-#define YYFPRINTF parser_fprintf
+#define parse_type(ps) builtin_type (ps->gdbarch ())
+#define parse_d_type(ps) builtin_d_type (ps->gdbarch ())
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
+ etc). */
+#define GDB_YY_REMAP_PREFIX d_
+#include "yy-remap.h"
/* The state of the parser, used internally when we are parsing the
expression. */
static struct parser_state *pstate = NULL;
+/* The current type stack. */
+static struct type_stack *type_stack;
+
int yyparse (void);
static int yylex (void);
-void yyerror (char *);
+static void yyerror (const char *);
+
+static int type_aggregate_p (struct type *);
+
+using namespace expr;
%}
struct type *type;
} typed_val_int;
struct {
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
} typed_val_float;
struct symbol *sym;
struct ttype tsym;
struct symtoken ssym;
int ival;
- struct block *bval;
+ int voidval;
enum exp_opcode opcode;
struct stoken_vector svec;
}
/* YYSTYPE gets defined by %union */
static int parse_number (struct parser_state *, const char *,
int, int, YYSTYPE *);
-
-static void push_expression_name (struct parser_state *, struct stoken);
%}
-%token <sval> IDENTIFIER
+%token <sval> IDENTIFIER UNKNOWN_NAME
%token <tsym> TYPENAME
%token <voidval> COMPLETE
CommaExpression:
AssignExpression
| AssignExpression ',' CommaExpression
- { write_exp_elt_opcode (pstate, BINOP_COMMA); }
+ { pstate->wrap2<comma_operation> (); }
;
AssignExpression:
ConditionalExpression
| ConditionalExpression '=' AssignExpression
- { write_exp_elt_opcode (pstate, BINOP_ASSIGN); }
+ { pstate->wrap2<assign_operation> (); }
| ConditionalExpression ASSIGN_MODIFY AssignExpression
- { write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY);
- write_exp_elt_opcode (pstate, $2);
- write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY); }
+ {
+ operation_up rhs = pstate->pop ();
+ operation_up lhs = pstate->pop ();
+ pstate->push_new<assign_modify_operation>
+ ($2, std::move (lhs), std::move (rhs));
+ }
;
ConditionalExpression:
OrOrExpression
| OrOrExpression '?' Expression ':' ConditionalExpression
- { write_exp_elt_opcode (pstate, TERNOP_COND); }
+ {
+ operation_up last = pstate->pop ();
+ operation_up mid = pstate->pop ();
+ operation_up first = pstate->pop ();
+ pstate->push_new<ternop_cond_operation>
+ (std::move (first), std::move (mid),
+ std::move (last));
+ }
;
OrOrExpression:
AndAndExpression
| OrOrExpression OROR AndAndExpression
- { write_exp_elt_opcode (pstate, BINOP_LOGICAL_OR); }
+ { pstate->wrap2<logical_or_operation> (); }
;
AndAndExpression:
OrExpression
| AndAndExpression ANDAND OrExpression
- { write_exp_elt_opcode (pstate, BINOP_LOGICAL_AND); }
+ { pstate->wrap2<logical_and_operation> (); }
;
OrExpression:
XorExpression
| OrExpression '|' XorExpression
- { write_exp_elt_opcode (pstate, BINOP_BITWISE_IOR); }
+ { pstate->wrap2<bitwise_ior_operation> (); }
;
XorExpression:
AndExpression
| XorExpression '^' AndExpression
- { write_exp_elt_opcode (pstate, BINOP_BITWISE_XOR); }
+ { pstate->wrap2<bitwise_xor_operation> (); }
;
AndExpression:
CmpExpression
| AndExpression '&' CmpExpression
- { write_exp_elt_opcode (pstate, BINOP_BITWISE_AND); }
+ { pstate->wrap2<bitwise_and_operation> (); }
;
CmpExpression:
EqualExpression:
ShiftExpression EQUAL ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_EQUAL); }
+ { pstate->wrap2<equal_operation> (); }
| ShiftExpression NOTEQUAL ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_NOTEQUAL); }
+ { pstate->wrap2<notequal_operation> (); }
;
IdentityExpression:
ShiftExpression IDENTITY ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_EQUAL); }
+ { pstate->wrap2<equal_operation> (); }
| ShiftExpression NOTIDENTITY ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_NOTEQUAL); }
+ { pstate->wrap2<notequal_operation> (); }
;
RelExpression:
ShiftExpression '<' ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_LESS); }
+ { pstate->wrap2<less_operation> (); }
| ShiftExpression LEQ ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_LEQ); }
+ { pstate->wrap2<leq_operation> (); }
| ShiftExpression '>' ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_GTR); }
+ { pstate->wrap2<gtr_operation> (); }
| ShiftExpression GEQ ShiftExpression
- { write_exp_elt_opcode (pstate, BINOP_GEQ); }
+ { pstate->wrap2<geq_operation> (); }
;
ShiftExpression:
AddExpression
| ShiftExpression LSH AddExpression
- { write_exp_elt_opcode (pstate, BINOP_LSH); }
+ { pstate->wrap2<lsh_operation> (); }
| ShiftExpression RSH AddExpression
- { write_exp_elt_opcode (pstate, BINOP_RSH); }
+ { pstate->wrap2<rsh_operation> (); }
;
AddExpression:
MulExpression
| AddExpression '+' MulExpression
- { write_exp_elt_opcode (pstate, BINOP_ADD); }
+ { pstate->wrap2<add_operation> (); }
| AddExpression '-' MulExpression
- { write_exp_elt_opcode (pstate, BINOP_SUB); }
+ { pstate->wrap2<sub_operation> (); }
| AddExpression '~' MulExpression
- { write_exp_elt_opcode (pstate, BINOP_CONCAT); }
+ { pstate->wrap2<concat_operation> (); }
;
MulExpression:
UnaryExpression
| MulExpression '*' UnaryExpression
- { write_exp_elt_opcode (pstate, BINOP_MUL); }
+ { pstate->wrap2<mul_operation> (); }
| MulExpression '/' UnaryExpression
- { write_exp_elt_opcode (pstate, BINOP_DIV); }
+ { pstate->wrap2<div_operation> (); }
| MulExpression '%' UnaryExpression
- { write_exp_elt_opcode (pstate, BINOP_REM); }
+ { pstate->wrap2<rem_operation> (); }
UnaryExpression:
'&' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_ADDR); }
+ { pstate->wrap<unop_addr_operation> (); }
| INCREMENT UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_PREINCREMENT); }
+ { pstate->wrap<preinc_operation> (); }
| DECREMENT UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_PREDECREMENT); }
+ { pstate->wrap<predec_operation> (); }
| '*' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_IND); }
+ { pstate->wrap<unop_ind_operation> (); }
| '-' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_NEG); }
+ { pstate->wrap<unary_neg_operation> (); }
| '+' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_PLUS); }
+ { pstate->wrap<unary_plus_operation> (); }
| '!' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_LOGICAL_NOT); }
+ { pstate->wrap<unary_logical_not_operation> (); }
| '~' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_COMPLEMENT); }
+ { pstate->wrap<unary_complement_operation> (); }
+| TypeExp '.' SIZEOF_KEYWORD
+ { pstate->wrap<unop_sizeof_operation> (); }
| CastExpression
| PowExpression
;
CastExpression:
CAST_KEYWORD '(' TypeExp ')' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_CAST);
- write_exp_elt_type (pstate, $3);
- write_exp_elt_opcode (pstate, UNOP_CAST); }
+ { pstate->wrap2<unop_cast_type_operation> (); }
/* C style cast is illegal D, but is still recognised in
the grammar, so we keep this around for convenience. */
| '(' TypeExp ')' UnaryExpression
- { write_exp_elt_opcode (pstate, UNOP_CAST);
- write_exp_elt_type (pstate, $2);
- write_exp_elt_opcode (pstate, UNOP_CAST); }
+ { pstate->wrap2<unop_cast_type_operation> (); }
;
PowExpression:
PostfixExpression
| PostfixExpression HATHAT UnaryExpression
- { write_exp_elt_opcode (pstate, BINOP_EXP); }
+ { pstate->wrap2<exp_operation> (); }
;
PostfixExpression:
PrimaryExpression
+| PostfixExpression '.' COMPLETE
+ {
+ structop_base_operation *op
+ = new structop_ptr_operation (pstate->pop (), "");
+ pstate->mark_struct_expression (op);
+ pstate->push (operation_up (op));
+ }
+| PostfixExpression '.' IDENTIFIER
+ {
+ pstate->push_new<structop_operation>
+ (pstate->pop (), copy_name ($3));
+ }
+| PostfixExpression '.' IDENTIFIER COMPLETE
+ {
+ structop_base_operation *op
+ = new structop_operation (pstate->pop (), copy_name ($3));
+ pstate->mark_struct_expression (op);
+ pstate->push (operation_up (op));
+ }
+| PostfixExpression '.' SIZEOF_KEYWORD
+ { pstate->wrap<unop_sizeof_operation> (); }
| PostfixExpression INCREMENT
- { write_exp_elt_opcode (pstate, UNOP_POSTINCREMENT); }
+ { pstate->wrap<postinc_operation> (); }
| PostfixExpression DECREMENT
- { write_exp_elt_opcode (pstate, UNOP_POSTDECREMENT); }
+ { pstate->wrap<postdec_operation> (); }
| CallExpression
| IndexExpression
| SliceExpression
ArgumentList:
AssignExpression
- { arglist_len = 1; }
+ { pstate->arglist_len = 1; }
| ArgumentList ',' AssignExpression
- { arglist_len++; }
+ { pstate->arglist_len++; }
;
ArgumentList_opt:
/* EMPTY */
- { arglist_len = 0; }
+ { pstate->arglist_len = 0; }
| ArgumentList
;
CallExpression:
PostfixExpression '('
- { start_arglist (); }
+ { pstate->start_arglist (); }
ArgumentList_opt ')'
- { write_exp_elt_opcode (pstate, OP_FUNCALL);
- write_exp_elt_longcst (pstate, (LONGEST) end_arglist ());
- write_exp_elt_opcode (pstate, OP_FUNCALL); }
+ {
+ std::vector<operation_up> args
+ = pstate->pop_vector (pstate->end_arglist ());
+ pstate->push_new<funcall_operation>
+ (pstate->pop (), std::move (args));
+ }
;
IndexExpression:
PostfixExpression '[' ArgumentList ']'
- { if (arglist_len > 0)
+ { if (pstate->arglist_len > 0)
{
- write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
- write_exp_elt_longcst (pstate, (LONGEST) arglist_len);
- write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
+ std::vector<operation_up> args
+ = pstate->pop_vector (pstate->arglist_len);
+ pstate->push_new<multi_subscript_operation>
+ (pstate->pop (), std::move (args));
}
else
- write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT);
+ pstate->wrap2<subscript_operation> ();
}
;
PostfixExpression '[' ']'
{ /* Do nothing. */ }
| PostfixExpression '[' AssignExpression DOTDOT AssignExpression ']'
- { write_exp_elt_opcode (pstate, TERNOP_SLICE); }
+ {
+ operation_up last = pstate->pop ();
+ operation_up mid = pstate->pop ();
+ operation_up first = pstate->pop ();
+ pstate->push_new<ternop_slice_operation>
+ (std::move (first), std::move (mid),
+ std::move (last));
+ }
;
PrimaryExpression:
'(' Expression ')'
{ /* Do nothing. */ }
| IdentifierExp
- { push_expression_name (pstate, $1); }
-| IdentifierExp '.' COMPLETE
- { struct stoken s;
- s.ptr = "";
- s.length = 0;
- push_expression_name (pstate, $1);
- mark_struct_expression (pstate);
- write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
- write_exp_string (pstate, s);
- write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
-| IdentifierExp '.' IDENTIFIER COMPLETE
- { push_expression_name (pstate, $1);
- mark_struct_expression (pstate);
- write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
- write_exp_string (pstate, $3);
- write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
+ { struct bound_minimal_symbol msymbol;
+ std::string copy = copy_name ($1);
+ struct field_of_this_result is_a_field_of_this;
+ struct block_symbol sym;
+
+ /* Handle VAR, which could be local or global. */
+ sym = lookup_symbol (copy.c_str (),
+ pstate->expression_context_block,
+ VAR_DOMAIN, &is_a_field_of_this);
+ if (sym.symbol && SYMBOL_CLASS (sym.symbol) != LOC_TYPEDEF)
+ {
+ if (symbol_read_needs_frame (sym.symbol))
+ pstate->block_tracker->update (sym);
+ pstate->push_new<var_value_operation> (sym);
+ }
+ else if (is_a_field_of_this.type != NULL)
+ {
+ /* It hangs off of `this'. Must not inadvertently convert from a
+ method call to data ref. */
+ pstate->block_tracker->update (sym);
+ operation_up thisop
+ = make_operation<op_this_operation> ();
+ pstate->push_new<structop_ptr_operation>
+ (std::move (thisop), std::move (copy));
+ }
+ else
+ {
+ /* Lookup foreign name in global static symbols. */
+ msymbol = lookup_bound_minimal_symbol (copy.c_str ());
+ if (msymbol.minsym != NULL)
+ pstate->push_new<var_msym_value_operation> (msymbol);
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error (_("No symbol table is loaded. Use the \"file\" command"));
+ else
+ error (_("No symbol \"%s\" in current context."),
+ copy.c_str ());
+ }
+ }
+| TypeExp '.' IdentifierExp
+ { struct type *type = check_typedef ($1);
+
+ /* Check if the qualified name is in the global
+ context. However if the symbol has not already
+ been resolved, it's not likely to be found. */
+ if (type->code () == TYPE_CODE_MODULE)
+ {
+ struct block_symbol sym;
+ const char *type_name = TYPE_SAFE_NAME (type);
+ int type_name_len = strlen (type_name);
+ std::string name
+ = string_printf ("%.*s.%.*s",
+ type_name_len, type_name,
+ $3.length, $3.ptr);
+
+ sym =
+ lookup_symbol (name.c_str (),
+ (const struct block *) NULL,
+ VAR_DOMAIN, NULL);
+ pstate->push_symbol (name.c_str (), sym);
+ }
+ else
+ {
+ /* Check if the qualified name resolves as a member
+ of an aggregate or an enum type. */
+ if (!type_aggregate_p (type))
+ error (_("`%s' is not defined as an aggregate type."),
+ TYPE_SAFE_NAME (type));
+
+ pstate->push_new<scope_operation>
+ (type, copy_name ($3));
+ }
+ }
| DOLLAR_VARIABLE
- { write_dollar_variable (pstate, $1); }
+ { pstate->push_dollar ($1); }
| NAME_OR_INT
{ YYSTYPE val;
- parse_number (pstate, $1.ptr, $1.length, 0, &val);
- write_exp_elt_opcode (pstate, OP_LONG);
- write_exp_elt_type (pstate, val.typed_val_int.type);
- write_exp_elt_longcst (pstate,
- (LONGEST) val.typed_val_int.val);
- write_exp_elt_opcode (pstate, OP_LONG); }
+ parse_number (pstate, $1.ptr, $1.length, 0, &val);
+ pstate->push_new<long_const_operation>
+ (val.typed_val_int.type, val.typed_val_int.val); }
| NULL_KEYWORD
{ struct type *type = parse_d_type (pstate)->builtin_void;
type = lookup_pointer_type (type);
- write_exp_elt_opcode (pstate, OP_LONG);
- write_exp_elt_type (pstate, type);
- write_exp_elt_longcst (pstate, (LONGEST) 0);
- write_exp_elt_opcode (pstate, OP_LONG); }
+ pstate->push_new<long_const_operation> (type, 0); }
| TRUE_KEYWORD
- { write_exp_elt_opcode (pstate, OP_BOOL);
- write_exp_elt_longcst (pstate, (LONGEST) 1);
- write_exp_elt_opcode (pstate, OP_BOOL); }
+ { pstate->push_new<bool_operation> (true); }
| FALSE_KEYWORD
- { write_exp_elt_opcode (pstate, OP_BOOL);
- write_exp_elt_longcst (pstate, (LONGEST) 0);
- write_exp_elt_opcode (pstate, OP_BOOL); }
+ { pstate->push_new<bool_operation> (false); }
| INTEGER_LITERAL
- { write_exp_elt_opcode (pstate, OP_LONG);
- write_exp_elt_type (pstate, $1.type);
- write_exp_elt_longcst (pstate, (LONGEST)($1.val));
- write_exp_elt_opcode (pstate, OP_LONG); }
+ { pstate->push_new<long_const_operation> ($1.type, $1.val); }
| FLOAT_LITERAL
- { write_exp_elt_opcode (pstate, OP_DOUBLE);
- write_exp_elt_type (pstate, $1.type);
- write_exp_elt_dblcst (pstate, $1.dval);
- write_exp_elt_opcode (pstate, 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);
+ }
| CHARACTER_LITERAL
{ struct stoken_vector vec;
vec.len = 1;
vec.tokens = &$1;
- write_exp_string_vector (pstate, $1.type, &vec); }
+ pstate->push_c_string (0, &vec); }
| StringExp
{ int i;
- write_exp_string_vector (pstate, 0, &$1);
+ pstate->push_c_string (0, &$1);
for (i = 0; i < $1.len; ++i)
free ($1.tokens[i].ptr);
free ($1.tokens); }
| ArrayLiteral
- { write_exp_elt_opcode (pstate, OP_ARRAY);
- write_exp_elt_longcst (pstate, (LONGEST) 0);
- write_exp_elt_longcst (pstate, (LONGEST) $1 - 1);
- write_exp_elt_opcode (pstate, OP_ARRAY); }
+ {
+ std::vector<operation_up> args
+ = pstate->pop_vector ($1);
+ pstate->push_new<array_operation>
+ (0, $1 - 1, std::move (args));
+ }
+| TYPEOF_KEYWORD '(' Expression ')'
+ { pstate->wrap<typeof_operation> (); }
;
ArrayLiteral:
'[' ArgumentList_opt ']'
- { $$ = arglist_len; }
+ { $$ = pstate->arglist_len; }
;
IdentifierExp:
IDENTIFIER
-| IdentifierExp '.' IDENTIFIER
- { $$.length = $1.length + $3.length + 1;
- if ($1.ptr + $1.length + 1 == $3.ptr
- && $1.ptr[$1.length] == '.')
- $$.ptr = $1.ptr; /* Optimization. */
- else
- {
- char *buf = malloc ($$.length + 1);
- make_cleanup (free, buf);
- sprintf (buf, "%.*s.%.*s",
- $1.length, $1.ptr, $3.length, $3.ptr);
- $$.ptr = buf;
- }
- }
;
StringExp:
vec->type = $1.type;
vec->length = $1.length;
- vec->ptr = malloc ($1.length + 1);
+ vec->ptr = (char *) malloc ($1.length + 1);
memcpy (vec->ptr, $1.ptr, $1.length + 1);
}
| StringExp STRING_LITERAL
for convenience. */
char *p;
++$$.len;
- $$.tokens = realloc ($$.tokens,
- $$.len * sizeof (struct typed_stoken));
+ $$.tokens
+ = XRESIZEVEC (struct typed_stoken, $$.tokens, $$.len);
- p = malloc ($2.length + 1);
+ p = (char *) malloc ($2.length + 1);
memcpy (p, $2.ptr, $2.length + 1);
$$.tokens[$$.len - 1].type = $2.type;
;
TypeExp:
- BasicType
- { write_exp_elt_opcode (pstate, OP_TYPE);
- write_exp_elt_type (pstate, $1);
- write_exp_elt_opcode (pstate, OP_TYPE); }
+ '(' TypeExp ')'
+ { /* Do nothing. */ }
+| BasicType
+ { pstate->push_new<type_operation> ($1); }
| BasicType BasicType2
- { $$ = follow_types ($1);
- write_exp_elt_opcode (pstate, OP_TYPE);
- write_exp_elt_type (pstate, $$);
- write_exp_elt_opcode (pstate, OP_TYPE);
+ { $$ = type_stack->follow_types ($1);
+ pstate->push_new<type_operation> ($$);
}
;
BasicType2:
'*'
- { push_type (tp_pointer); }
+ { type_stack->push (tp_pointer); }
| '*' BasicType2
- { push_type (tp_pointer); }
+ { type_stack->push (tp_pointer); }
| '[' INTEGER_LITERAL ']'
- { push_type_int ($2.val);
- push_type (tp_array); }
+ { type_stack->push ($2.val);
+ type_stack->push (tp_array); }
| '[' INTEGER_LITERAL ']' BasicType2
- { push_type_int ($2.val);
- push_type (tp_array); }
+ { type_stack->push ($2.val);
+ type_stack->push (tp_array); }
;
BasicType:
TYPENAME
{ $$ = $1.type; }
-| CLASS_KEYWORD IdentifierExp
- { $$ = lookup_struct (copy_name ($2),
- expression_context_block); }
-| CLASS_KEYWORD COMPLETE
- { mark_completion_tag (TYPE_CODE_STRUCT, "", 0);
- $$ = NULL; }
-| CLASS_KEYWORD IdentifierExp COMPLETE
- { mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr, $2.length);
- $$ = NULL; }
-| STRUCT_KEYWORD IdentifierExp
- { $$ = lookup_struct (copy_name ($2),
- expression_context_block); }
-| STRUCT_KEYWORD COMPLETE
- { mark_completion_tag (TYPE_CODE_STRUCT, "", 0);
- $$ = NULL; }
-| STRUCT_KEYWORD IdentifierExp COMPLETE
- { mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr, $2.length);
- $$ = NULL; }
-| UNION_KEYWORD IdentifierExp
- { $$ = lookup_union (copy_name ($2),
- expression_context_block); }
-| UNION_KEYWORD COMPLETE
- { mark_completion_tag (TYPE_CODE_UNION, "", 0);
- $$ = NULL; }
-| UNION_KEYWORD IdentifierExp COMPLETE
- { mark_completion_tag (TYPE_CODE_UNION, $2.ptr, $2.length);
- $$ = NULL; }
-| ENUM_KEYWORD IdentifierExp
- { $$ = lookup_enum (copy_name ($2),
- expression_context_block); }
-| ENUM_KEYWORD COMPLETE
- { mark_completion_tag (TYPE_CODE_ENUM, "", 0);
- $$ = NULL; }
-| ENUM_KEYWORD IdentifierExp COMPLETE
- { mark_completion_tag (TYPE_CODE_ENUM, $2.ptr, $2.length);
- $$ = NULL; }
;
%%
+/* Return true if the type is aggregate-like. */
+
+static int
+type_aggregate_p (struct type *type)
+{
+ return (type->code () == TYPE_CODE_STRUCT
+ || type->code () == TYPE_CODE_UNION
+ || type->code () == TYPE_CODE_MODULE
+ || (type->code () == TYPE_CODE_ENUM
+ && type->is_declared_class ()));
+}
+
/* Take care of parsing a number (anything that starts with a digit).
Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */
if (parsed_float)
{
- const struct builtin_d_type *builtin_d_types;
- const char *suffix;
- int suffix_len;
char *s, *sp;
/* Strip out all embedded '_' before passing to parse_float. */
*sp = '\0';
len = strlen (s);
- if (! parse_float (s, len, &putithere->typed_val_float.dval, &suffix))
- return ERROR;
-
- suffix_len = s + len - suffix;
-
- if (suffix_len == 0)
- {
- putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_double;
- }
- else if (suffix_len == 1)
+ /* Check suffix for `i' , `fi' or `li' (idouble, ifloat or ireal). */
+ if (len >= 1 && tolower (s[len - 1]) == 'i')
{
- /* Check suffix for `f', `l', or `i' (float, real, or idouble). */
- if (tolower (*suffix) == 'f')
+ if (len >= 2 && tolower (s[len - 2]) == 'f')
{
putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_float;
+ = parse_d_type (ps)->builtin_ifloat;
+ len -= 2;
}
- else if (tolower (*suffix) == 'l')
+ else if (len >= 2 && tolower (s[len - 2]) == 'l')
{
putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_real;
+ = parse_d_type (ps)->builtin_ireal;
+ len -= 2;
}
- else if (tolower (*suffix) == 'i')
+ else
{
putithere->typed_val_float.type
= parse_d_type (ps)->builtin_idouble;
+ len -= 1;
}
- else
- return ERROR;
}
- else if (suffix_len == 2)
+ /* Check suffix for `f' or `l'' (float or real). */
+ else if (len >= 1 && tolower (s[len - 1]) == 'f')
{
- /* Check suffix for `fi' or `li' (ifloat or ireal). */
- if (tolower (suffix[0]) == 'f' && tolower (suffix[1] == 'i'))
- {
- putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_ifloat;
- }
- else if (tolower (suffix[0]) == 'l' && tolower (suffix[1] == 'i'))
- {
- putithere->typed_val_float.type
- = parse_d_type (ps)->builtin_ireal;
- }
- else
- return ERROR;
+ putithere->typed_val_float.type
+ = parse_d_type (ps)->builtin_float;
+ len -= 1;
+ }
+ else if (len >= 1 && tolower (s[len - 1]) == 'l')
+ {
+ putithere->typed_val_float.type
+ = parse_d_type (ps)->builtin_real;
+ len -= 1;
}
+ /* Default type if no suffix. */
else
+ {
+ putithere->typed_val_float.type
+ = parse_d_type (ps)->builtin_double;
+ }
+
+ if (!parse_float (s, len,
+ putithere->typed_val_float.type,
+ putithere->typed_val_float.val))
return ERROR;
return FLOAT_LITERAL;
if (base > 10 && c >= 'a' && c <= 'f')
{
if (found_suffix)
- return ERROR;
+ return ERROR;
n += i = c - 'a' + 10;
}
else if (c == 'l' && long_p == 0)
else
value->type = C_STRING;
- value->ptr = obstack_base (&tempbuf);
+ value->ptr = (char *) obstack_base (&tempbuf);
value->length = obstack_object_size (&tempbuf);
*outptr = tokptr;
struct token
{
- char *operator;
+ const char *oper;
int token;
enum exp_opcode opcode;
};
{"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR},
{"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
{"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
- {"++", INCREMENT, BINOP_END},
- {"--", DECREMENT, BINOP_END},
- {"&&", ANDAND, BINOP_END},
- {"||", OROR, BINOP_END},
- {"^^", HATHAT, BINOP_END},
- {"<<", LSH, BINOP_END},
- {">>", RSH, BINOP_END},
- {"==", EQUAL, BINOP_END},
- {"!=", NOTEQUAL, BINOP_END},
- {"<=", LEQ, BINOP_END},
- {">=", GEQ, BINOP_END},
- {"..", DOTDOT, BINOP_END},
+ {"++", INCREMENT, OP_NULL},
+ {"--", DECREMENT, OP_NULL},
+ {"&&", ANDAND, OP_NULL},
+ {"||", OROR, OP_NULL},
+ {"^^", HATHAT, OP_NULL},
+ {"<<", LSH, OP_NULL},
+ {">>", RSH, OP_NULL},
+ {"==", EQUAL, OP_NULL},
+ {"!=", NOTEQUAL, OP_NULL},
+ {"<=", LEQ, OP_NULL},
+ {">=", GEQ, OP_NULL},
+ {"..", DOTDOT, OP_NULL},
};
/* Identifier-like tokens. */
static const struct token ident_tokens[] =
{
- {"is", IDENTITY, BINOP_END},
- {"!is", NOTIDENTITY, BINOP_END},
+ {"is", IDENTITY, OP_NULL},
+ {"!is", NOTIDENTITY, OP_NULL},
{"cast", CAST_KEYWORD, OP_NULL},
{"const", CONST_KEYWORD, OP_NULL},
{"template", TEMPLATE_KEYWORD, OP_NULL},
};
-/* If NAME is a type name in this scope, return it. */
-
-static struct type *
-d_type_from_name (struct stoken name)
-{
- struct symbol *sym;
- char *copy = copy_name (name);
-
- sym = lookup_symbol (copy, expression_context_block,
- STRUCT_DOMAIN, NULL);
- if (sym != NULL)
- return SYMBOL_TYPE (sym);
-
- return NULL;
-}
-
-/* If NAME is a module name in this scope, return it. */
-
-static struct type *
-d_module_from_name (struct stoken name)
-{
- struct symbol *sym;
- char *copy = copy_name (name);
-
- sym = lookup_symbol (copy, expression_context_block,
- MODULE_DOMAIN, NULL);
- if (sym != NULL)
- return SYMBOL_TYPE (sym);
-
- return NULL;
-}
-
-/* If NAME is a valid variable name in this scope, push it and return 1.
- Otherwise, return 0. */
-
-static int
-push_variable (struct parser_state *ps, struct stoken name)
-{
- char *copy = copy_name (name);
- struct field_of_this_result is_a_field_of_this;
- struct symbol *sym;
- sym = lookup_symbol (copy, expression_context_block, VAR_DOMAIN,
- &is_a_field_of_this);
- if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- {
- if (symbol_read_needs_frame (sym))
- {
- if (innermost_block == 0 ||
- contained_in (block_found, innermost_block))
- innermost_block = block_found;
- }
-
- write_exp_elt_opcode (ps, OP_VAR_VALUE);
- /* We want to use the selected frame, not another more inner frame
- which happens to be in the same block. */
- write_exp_elt_block (ps, NULL);
- write_exp_elt_sym (ps, sym);
- write_exp_elt_opcode (ps, OP_VAR_VALUE);
- return 1;
- }
- if (is_a_field_of_this.type != NULL)
- {
- /* It hangs off of `this'. Must not inadvertently convert from a
- method call to data ref. */
- if (innermost_block == 0 ||
- contained_in (block_found, innermost_block))
- innermost_block = block_found;
- write_exp_elt_opcode (ps, OP_THIS);
- write_exp_elt_opcode (ps, OP_THIS);
- write_exp_elt_opcode (ps, STRUCTOP_PTR);
- write_exp_string (ps, name);
- write_exp_elt_opcode (ps, STRUCTOP_PTR);
- return 1;
- }
- return 0;
-}
-
-/* Assuming a reference expression has been pushed, emit the
- STRUCTOP_PTR ops to access the field named NAME. If NAME is a
- qualified name (has '.'), generate a field access for each part. */
-
-static void
-push_fieldnames (struct parser_state *ps, struct stoken name)
-{
- int i;
- struct stoken token;
- token.ptr = name.ptr;
- for (i = 0; ; i++)
- {
- if (i == name.length || name.ptr[i] == '.')
- {
- /* token.ptr is start of current field name. */
- token.length = &name.ptr[i] - token.ptr;
- write_exp_elt_opcode (ps, STRUCTOP_PTR);
- write_exp_string (ps, token);
- write_exp_elt_opcode (ps, STRUCTOP_PTR);
- token.ptr += token.length + 1;
- }
- if (i >= name.length)
- break;
- }
-}
-
-/* Helper routine for push_expression_name. Handle a TYPE symbol,
- where DOT_INDEX is the index of the first '.' if NAME is part of
- a qualified type. */
-
-static void
-push_type_name (struct parser_state *ps, struct type *type,
- struct stoken name, int dot_index)
-{
- if (dot_index == name.length)
- {
- write_exp_elt_opcode (ps, OP_TYPE);
- write_exp_elt_type (ps, type);
- write_exp_elt_opcode (ps, OP_TYPE);
- }
- else
- {
- struct stoken token;
-
- token.ptr = name.ptr;
- token.length = dot_index;
-
- dot_index = 0;
-
- while (dot_index < name.length && name.ptr[dot_index] != '.')
- dot_index++;
- token.ptr = name.ptr;
- token.length = dot_index;
-
- write_exp_elt_opcode (ps, OP_SCOPE);
- write_exp_elt_type (ps, type);
- write_exp_string (ps, token);
- write_exp_elt_opcode (ps, OP_SCOPE);
-
- if (dot_index < name.length)
- {
- dot_index++;
- name.ptr += dot_index;
- name.length -= dot_index;
- push_fieldnames (ps, name);
- }
- }
-}
-
-/* Helper routine for push_expression_name. Like push_type_name,
- but used when TYPE is a module. Returns 1 on pushing the symbol. */
-
-static int
-push_module_name (struct parser_state *ps, struct type *module,
- struct stoken name, int dot_index)
-{
- if (dot_index == name.length)
- {
- write_exp_elt_opcode (ps, OP_TYPE);
- write_exp_elt_type (ps, module);
- write_exp_elt_opcode (ps, OP_TYPE);
- return 1;
- }
- else
- {
- struct symbol *sym;
- char *copy;
-
- copy = copy_name (name);
- sym = lookup_symbol_in_static_block (copy, expression_context_block,
- VAR_DOMAIN);
- if (sym != NULL)
- sym = lookup_global_symbol (copy, expression_context_block,
- VAR_DOMAIN);
-
- if (sym != NULL)
- {
- if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- {
- write_exp_elt_opcode (ps, OP_VAR_VALUE);
- write_exp_elt_block (ps, NULL);
- write_exp_elt_sym (ps, sym);
- write_exp_elt_opcode (ps, OP_VAR_VALUE);
- }
- else
- {
- write_exp_elt_opcode (ps, OP_TYPE);
- write_exp_elt_type (ps, SYMBOL_TYPE (sym));
- write_exp_elt_opcode (ps, OP_TYPE);
- }
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Handle NAME in an expression (or LHS), which could be a
- variable, type, or module. */
-
-static void
-push_expression_name (struct parser_state *ps, struct stoken name)
-{
- struct stoken token;
- struct type *typ;
- struct bound_minimal_symbol msymbol;
- char *copy;
- int doti;
-
- /* Handle VAR, which could be local or global. */
- if (push_variable (ps, name) != 0)
- return;
-
- /* Handle MODULE. */
- typ = d_module_from_name (name);
- if (typ != NULL)
- {
- if (push_module_name (ps, typ, name, name.length) != 0)
- return;
- }
-
- /* Handle TYPE. */
- typ = d_type_from_name (name);
- if (typ != NULL)
- {
- push_type_name (ps, typ, name, name.length);
- return;
- }
-
- /* Handle VAR.FIELD1..FIELDN. */
- for (doti = 0; doti < name.length; doti++)
- {
- if (name.ptr[doti] == '.')
- {
- token.ptr = name.ptr;
- token.length = doti;
-
- if (push_variable (ps, token) != 0)
- {
- token.ptr = name.ptr + doti + 1;
- token.length = name.length - doti - 1;
- push_fieldnames (ps, token);
- return;
- }
- break;
- }
- }
-
- /* Continue looking if we found a '.' in the name. */
- if (doti < name.length)
- {
- token.ptr = name.ptr;
- for (;;)
- {
- token.length = doti;
-
- /* Handle PACKAGE.MODULE. */
- typ = d_module_from_name (token);
- if (typ != NULL)
- {
- if (push_module_name (ps, typ, name, doti) != 0)
- return;
- }
- /* Handle TYPE.FIELD1..FIELDN. */
- typ = d_type_from_name (token);
- if (typ != NULL)
- {
- push_type_name (ps, typ, name, doti);
- return;
- }
-
- if (doti >= name.length)
- break;
- doti++; /* Skip '.' */
- while (doti < name.length && name.ptr[doti] != '.')
- doti++;
- }
- }
-
- /* Lookup foreign name in global static symbols. */
- copy = copy_name (name);
- msymbol = lookup_bound_minimal_symbol (copy);
- if (msymbol.minsym != NULL)
- write_exp_msymbol (ps, msymbol);
- else if (!have_full_symbols () && !have_partial_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command"));
- else
- error (_("No symbol \"%s\" in current context."), copy);
-}
-
/* This is set if a NAME token appeared at the very end of the input
string, with no whitespace separating the name from the EOF. This
is used only when parsing to do field name completion. */
This is used only when parsing to do field name completion. */
static int last_was_structop;
+/* Depth of parentheses. */
+static int paren_depth;
+
/* Read one token, getting characters through lexptr. */
static int
-yylex (void)
+lex_one_token (struct parser_state *par_state)
{
int c;
int namelen;
- unsigned int i;
const char *tokstart;
int saw_structop = last_was_structop;
- char *copy;
last_was_structop = 0;
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].operator, 3) == 0)
+ for (const auto &token : tokentab3)
+ if (strncmp (tokstart, token.oper, 3) == 0)
{
- lexptr += 3;
- yylval.opcode = tokentab3[i].opcode;
- return tokentab3[i].token;
+ pstate->lexptr += 3;
+ yylval.opcode = token.opcode;
+ return token.token;
}
/* See if it is a special token of length 2. */
- for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
- if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
+ for (const auto &token : tokentab2)
+ if (strncmp (tokstart, token.oper, 2) == 0)
{
- lexptr += 2;
- yylval.opcode = tokentab2[i].opcode;
- return tokentab2[i].token;
+ pstate->lexptr += 2;
+ yylval.opcode = token.opcode;
+ return token.token;
}
switch (c = *tokstart)
else if (saw_structop)
return COMPLETE;
else
- return 0;
+ return 0;
case ' ':
case '\t':
case '\n':
- lexptr++;
+ pstate->lexptr++;
goto retry;
case '[':
case '(':
paren_depth++;
- lexptr++;
+ pstate->lexptr++;
return c;
case ']':
if (paren_depth == 0)
return 0;
paren_depth--;
- lexptr++;
+ pstate->lexptr++;
return c;
case ',':
- if (comma_terminates && paren_depth == 0)
+ 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)
+ if (pstate->parse_completion)
last_was_structop = 1;
goto symbol; /* Nope, must be a symbol. */
}
- /* FALL THRU into number case. */
+ /* FALL THRU. */
case '0':
case '1':
/* We will take any letters or digits, ignoring any embedded '_'.
parse_number will complain if past the radix, or if L or U are
not final. */
- else if ((*p < '0' || *p > '9') && (*p != '_') &&
- ((*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z')))
+ else if ((*p < '0' || *p > '9') && (*p != '_')
+ && ((*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z')))
break;
}
- toktype = parse_number (pstate, tokstart, p - tokstart,
+ toktype = parse_number (par_state, tokstart, p - tokstart,
got_dot|got_e, &yylval);
if (toktype == ERROR)
{
err_copy[p - tokstart] = 0;
error (_("Invalid number \"%s\"."), err_copy);
}
- lexptr = p;
+ pstate->lexptr = p;
return toktype;
}
if (strncmp (p, "entry", len) == 0 && !isalnum (p[len])
&& p[len] != '_')
{
- lexptr = &p[len];
+ pstate->lexptr = &p[len];
return ENTRY;
}
}
case '{':
case '}':
symbol:
- lexptr++;
+ pstate->lexptr++;
return c;
case '\'':
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)
else if (host_len > 2 && c == '\'')
{
++tokstart;
- namelen = lexptr - tokstart - 1;
+ namelen = pstate->lexptr - tokstart - 1;
goto tryname;
}
else if (host_len > 1)
const char *p = tokstart + namelen + 1;
while (*p == ' ' || *p == '\t')
- p++;
+ p++;
if (*p >= '0' && *p <= '9')
- return 0;
+ return 0;
}
- lexptr += namelen;
+ pstate->lexptr += namelen;
tryname:
yylval.sval.length = namelen;
/* Catch specific keywords. */
- copy = copy_name (yylval.sval);
- for (i = 0; i < sizeof ident_tokens / sizeof ident_tokens[0]; i++)
- if (strcmp (copy, ident_tokens[i].operator) == 0)
+ std::string copy = copy_name (yylval.sval);
+ for (const auto &token : ident_tokens)
+ if (copy == token.oper)
{
/* It is ok to always set this, even though we don't always
strictly need to. */
- yylval.opcode = ident_tokens[i].opcode;
- return ident_tokens[i].token;
+ yylval.opcode = token.opcode;
+ return token.token;
}
if (*tokstart == '$')
return DOLLAR_VARIABLE;
yylval.tsym.type
- = language_lookup_primitive_type (parse_language (pstate),
- parse_gdbarch (pstate), copy);
+ = language_lookup_primitive_type (par_state->language (),
+ par_state->gdbarch (), copy.c_str ());
if (yylval.tsym.type != NULL)
return TYPENAME;
|| (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10))
{
YYSTYPE newlval; /* Its value is ignored. */
- int hextype = parse_number (pstate, tokstart, namelen, 0, &newlval);
+ int hextype = parse_number (par_state, tokstart, namelen, 0, &newlval);
if (hextype == INTEGER_LITERAL)
return NAME_OR_INT;
}
- if (parse_completion && *lexptr == '\0')
+ if (pstate->parse_completion && *pstate->lexptr == '\0')
saw_name_at_eof = 1;
return IDENTIFIER;
}
+/* An object of this type is pushed on a FIFO by the "outer" lexer. */
+struct token_and_value
+{
+ int token;
+ YYSTYPE value;
+};
+
+
+/* A FIFO of tokens that have been read but not yet returned to the
+ parser. */
+static std::vector<token_and_value> token_fifo;
+
+/* Non-zero if the lexer should return tokens from the FIFO. */
+static int popping;
+
+/* Temporary storage for yylex; this holds symbol names as they are
+ built up. */
+static auto_obstack name_obstack;
+
+/* Classify an IDENTIFIER token. The contents of the token are in `yylval'.
+ Updates yylval and returns the new token type. BLOCK is the block
+ in which lookups start; this can be NULL to mean the global scope. */
+
+static int
+classify_name (struct parser_state *par_state, const struct block *block)
+{
+ struct block_symbol sym;
+ struct field_of_this_result is_a_field_of_this;
+
+ std::string copy = copy_name (yylval.sval);
+
+ sym = lookup_symbol (copy.c_str (), block, VAR_DOMAIN, &is_a_field_of_this);
+ if (sym.symbol && SYMBOL_CLASS (sym.symbol) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym.symbol);
+ return TYPENAME;
+ }
+ else if (sym.symbol == NULL)
+ {
+ /* Look-up first for a module name, then a type. */
+ sym = lookup_symbol (copy.c_str (), block, MODULE_DOMAIN, NULL);
+ if (sym.symbol == NULL)
+ sym = lookup_symbol (copy.c_str (), block, STRUCT_DOMAIN, NULL);
+
+ if (sym.symbol != NULL)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym.symbol);
+ return TYPENAME;
+ }
+
+ return UNKNOWN_NAME;
+ }
+
+ return IDENTIFIER;
+}
+
+/* Like classify_name, but used by the inner loop of the lexer, when a
+ name might have already been seen. CONTEXT is the context type, or
+ NULL if this is the first component of a name. */
+
+static int
+classify_inner_name (struct parser_state *par_state,
+ const struct block *block, struct type *context)
+{
+ struct type *type;
+
+ if (context == NULL)
+ return classify_name (par_state, block);
+
+ type = check_typedef (context);
+ if (!type_aggregate_p (type))
+ return ERROR;
+
+ std::string copy = copy_name (yylval.ssym.stoken);
+ yylval.ssym.sym = d_lookup_nested_symbol (type, copy.c_str (), block);
+
+ if (yylval.ssym.sym.symbol == NULL)
+ return ERROR;
+
+ if (SYMBOL_CLASS (yylval.ssym.sym.symbol) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (yylval.ssym.sym.symbol);
+ return TYPENAME;
+ }
+
+ return IDENTIFIER;
+}
+
+/* The outer level of a two-level lexer. This calls the inner lexer
+ to return tokens. It then either returns these tokens, or
+ aggregates them into a larger token. This lets us work around a
+ problem in our parsing approach, where the parser could not
+ distinguish between qualified names and qualified types at the
+ right point. */
+
+static int
+yylex (void)
+{
+ token_and_value current;
+ int last_was_dot;
+ struct type *context_type = NULL;
+ int last_to_examine, next_to_examine, checkpoint;
+ const struct block *search_block;
+
+ if (popping && !token_fifo.empty ())
+ goto do_pop;
+ popping = 0;
+
+ /* Read the first token and decide what to do. */
+ current.token = lex_one_token (pstate);
+ if (current.token != IDENTIFIER && current.token != '.')
+ return current.token;
+
+ /* Read any sequence of alternating "." and identifier tokens into
+ the token FIFO. */
+ current.value = yylval;
+ token_fifo.push_back (current);
+ last_was_dot = current.token == '.';
+
+ while (1)
+ {
+ current.token = lex_one_token (pstate);
+ current.value = yylval;
+ token_fifo.push_back (current);
+
+ if ((last_was_dot && current.token != IDENTIFIER)
+ || (!last_was_dot && current.token != '.'))
+ break;
+
+ last_was_dot = !last_was_dot;
+ }
+ popping = 1;
+
+ /* We always read one extra token, so compute the number of tokens
+ to examine accordingly. */
+ last_to_examine = token_fifo.size () - 2;
+ next_to_examine = 0;
+
+ current = token_fifo[next_to_examine];
+ ++next_to_examine;
+
+ /* If we are not dealing with a typename, now is the time to find out. */
+ if (current.token == IDENTIFIER)
+ {
+ yylval = current.value;
+ current.token = classify_name (pstate, pstate->expression_context_block);
+ current.value = yylval;
+ }
+
+ /* If the IDENTIFIER is not known, it could be a package symbol,
+ first try building up a name until we find the qualified module. */
+ if (current.token == UNKNOWN_NAME)
+ {
+ name_obstack.clear ();
+ obstack_grow (&name_obstack, current.value.sval.ptr,
+ current.value.sval.length);
+
+ last_was_dot = 0;
+
+ while (next_to_examine <= last_to_examine)
+ {
+ token_and_value next;
+
+ next = token_fifo[next_to_examine];
+ ++next_to_examine;
+
+ if (next.token == IDENTIFIER && last_was_dot)
+ {
+ /* Update the partial name we are constructing. */
+ obstack_grow_str (&name_obstack, ".");
+ obstack_grow (&name_obstack, next.value.sval.ptr,
+ next.value.sval.length);
+
+ yylval.sval.ptr = (char *) obstack_base (&name_obstack);
+ yylval.sval.length = obstack_object_size (&name_obstack);
+
+ current.token = classify_name (pstate,
+ pstate->expression_context_block);
+ current.value = yylval;
+
+ /* We keep going until we find a TYPENAME. */
+ if (current.token == TYPENAME)
+ {
+ /* Install it as the first token in the FIFO. */
+ token_fifo[0] = current;
+ token_fifo.erase (token_fifo.begin () + 1,
+ token_fifo.begin () + next_to_examine);
+ break;
+ }
+ }
+ else if (next.token == '.' && !last_was_dot)
+ last_was_dot = 1;
+ else
+ {
+ /* We've reached the end of the name. */
+ break;
+ }
+ }
+
+ /* Reset our current token back to the start, if we found nothing
+ this means that we will just jump to do pop. */
+ current = token_fifo[0];
+ next_to_examine = 1;
+ }
+ if (current.token != TYPENAME && current.token != '.')
+ goto do_pop;
+
+ name_obstack.clear ();
+ checkpoint = 0;
+ if (current.token == '.')
+ search_block = NULL;
+ else
+ {
+ gdb_assert (current.token == TYPENAME);
+ search_block = pstate->expression_context_block;
+ obstack_grow (&name_obstack, current.value.sval.ptr,
+ current.value.sval.length);
+ context_type = current.value.tsym.type;
+ checkpoint = 1;
+ }
+
+ last_was_dot = current.token == '.';
+
+ while (next_to_examine <= last_to_examine)
+ {
+ token_and_value next;
+
+ next = token_fifo[next_to_examine];
+ ++next_to_examine;
+
+ if (next.token == IDENTIFIER && last_was_dot)
+ {
+ int classification;
+
+ yylval = next.value;
+ classification = classify_inner_name (pstate, search_block,
+ context_type);
+ /* We keep going until we either run out of names, or until
+ we have a qualified name which is not a type. */
+ if (classification != TYPENAME && classification != IDENTIFIER)
+ break;
+
+ /* Accept up to this token. */
+ checkpoint = next_to_examine;
+
+ /* Update the partial name we are constructing. */
+ if (context_type != NULL)
+ {
+ /* We don't want to put a leading "." into the name. */
+ obstack_grow_str (&name_obstack, ".");
+ }
+ obstack_grow (&name_obstack, next.value.sval.ptr,
+ next.value.sval.length);
+
+ yylval.sval.ptr = (char *) obstack_base (&name_obstack);
+ yylval.sval.length = obstack_object_size (&name_obstack);
+ current.value = yylval;
+ current.token = classification;
+
+ last_was_dot = 0;
+
+ if (classification == IDENTIFIER)
+ break;
+
+ context_type = yylval.tsym.type;
+ }
+ else if (next.token == '.' && !last_was_dot)
+ last_was_dot = 1;
+ else
+ {
+ /* We've reached the end of the name. */
+ break;
+ }
+ }
+
+ /* If we have a replacement token, install it as the first token in
+ the FIFO, and delete the other constituent tokens. */
+ if (checkpoint > 0)
+ {
+ token_fifo[0] = current;
+ if (checkpoint > 1)
+ token_fifo.erase (token_fifo.begin () + 1,
+ token_fifo.begin () + checkpoint);
+ }
+
+ do_pop:
+ current = token_fifo[0];
+ token_fifo.erase (token_fifo.begin ());
+ yylval = current.value;
+ return current.token;
+}
+
int
d_parse (struct parser_state *par_state)
{
- int result;
- struct cleanup *back_to;
-
/* Setting up the parser state. */
+ scoped_restore pstate_restore = make_scoped_restore (&pstate);
gdb_assert (par_state != NULL);
pstate = par_state;
- back_to = make_cleanup (null_cleanup, NULL);
+ scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
+ parser_debug);
- make_cleanup_restore_integer (&yydebug);
- make_cleanup_clear_parser_state (&pstate);
- yydebug = parser_debug;
+ struct type_stack stack;
+ scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
+ &stack);
/* Initialize some state used by the lexer. */
last_was_structop = 0;
saw_name_at_eof = 0;
+ paren_depth = 0;
- result = yyparse ();
- do_cleanups (back_to);
+ token_fifo.clear ();
+ popping = 0;
+ name_obstack.clear ();
+
+ int result = yyparse ();
+ if (!result)
+ pstate->set_operation (pstate->pop ());
return result;
}
-void
-yyerror (char *msg)
+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 ? msg : "error"), lexptr);
+ error (_("A %s in expression, near `%s'."), msg, pstate->lexptr);
}