aboutsummaryrefslogtreecommitdiff
path: root/gdb/parser-defs.h
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2021-03-08 07:27:57 -0700
committerTom Tromey <tom@tromey.com>2021-03-08 07:28:37 -0700
commit8227d9e2f4af14c7e36f1792747bd5d7edf71d6a (patch)
treeccd72473a386dc22c44b237893aea832b1e78451 /gdb/parser-defs.h
parent4933522da0d59823d2bfef3706e2252203365e9c (diff)
downloadgdb-8227d9e2f4af14c7e36f1792747bd5d7edf71d6a.zip
gdb-8227d9e2f4af14c7e36f1792747bd5d7edf71d6a.tar.gz
gdb-8227d9e2f4af14c7e36f1792747bd5d7edf71d6a.tar.bz2
Add operation-related methods to parser_state
This adds several operation-related methods to parser_state. These methods make it more convenient to change the parsers to be operation-based. Because byacc has poor support for C++, a stack of operations is added to parser_state. A parser can push operations, then later pop them for combination into new operations. This approach avoids the memory leaks that would result if raw pointers were used in the parsers, at the cost of parser productions not being type-safe (they can't indicate that they return an operation). This also introduces analogs of some write_exp functions, like write_exp_string_vector, write_dollar_variable, and write_exp_symbol_reference. gdb/ChangeLog 2021-03-08 Tom Tromey <tom@tromey.com> * parser-defs.h (struct parser_state) <push, push_new, push_c_string, push_symbol, push_dollar, pop, pop_vector, wrap, wrap2>: New methods. <m_operations>: New member. * parse.c (parser_state::push_c_string) (parser_state::push_symbol, parser_state::push_dollar): New methods.
Diffstat (limited to 'gdb/parser-defs.h')
-rw-r--r--gdb/parser-defs.h63
1 files changed, 63 insertions, 0 deletions
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 9f70ff9..6932559 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -173,6 +173,66 @@ struct parser_state : public expr_builder
void mark_completion_tag (enum type_code tag, const char *ptr, int length);
+ /* Push an operation on the stack. */
+ void push (expr::operation_up &&op)
+ {
+ m_operations.push_back (std::move (op));
+ }
+
+ /* Create a new operation and push it on the stack. */
+ template<typename T, typename... Arg>
+ void push_new (Arg... args)
+ {
+ m_operations.emplace_back (new T (std::forward<Arg> (args)...));
+ }
+
+ /* Push a new C string operation. */
+ void push_c_string (int, struct stoken_vector *vec);
+
+ /* Push a symbol reference. If SYM is nullptr, look for a minimal
+ symbol. */
+ void push_symbol (const char *name, block_symbol sym);
+
+ /* Push a reference to $mumble. This may result in a convenience
+ variable, a history reference, or a register. */
+ void push_dollar (struct stoken str);
+
+ /* Pop an operation from the stack. */
+ expr::operation_up pop ()
+ {
+ expr::operation_up result = std::move (m_operations.back ());
+ m_operations.pop_back ();
+ return result;
+ }
+
+ /* Pop N elements from the stack and return a vector. */
+ std::vector<expr::operation_up> pop_vector (int n)
+ {
+ std::vector<expr::operation_up> result (n);
+ for (int i = 1; i <= n; ++i)
+ result[n - i] = pop ();
+ return result;
+ }
+
+ /* A helper that pops an operation, wraps it in some other
+ operation, and pushes it again. */
+ template<typename T>
+ void wrap ()
+ {
+ using namespace expr;
+ operation_up v = ::expr::make_operation<T> (pop ());
+ push (std::move (v));
+ }
+
+ /* A helper that pops two operations, wraps them in some other
+ operation, and pushes the result. */
+ template<typename T>
+ void wrap2 ()
+ {
+ expr::operation_up rhs = pop ();
+ expr::operation_up lhs = pop ();
+ push (expr::make_operation<T> (std::move (lhs), std::move (rhs)));
+ }
/* If this is nonzero, this block is used as the lexical context for
symbol names. */
@@ -221,6 +281,9 @@ private:
arguments contain other function calls. */
std::vector<int> m_funcall_chain;
+
+ /* Stack of operations. */
+ std::vector<expr::operation_up> m_operations;
};
/* When parsing expressions we track the innermost block that was