From 8d06efa98b37375ac723c504bc8cf1f0cab8ae7c Mon Sep 17 00:00:00 2001
From: pompolic <pompolic@special-circumstanc.es>
Date: Thu, 9 Jun 2022 21:12:34 +0200
Subject: [PATCH] (WIP) Deduplicate some code

- Also add hammer-parse-apply to readme
---
 gdb-port/README.md           | 10 ++++++++++
 gdb-port/commands.py         | 14 ++------------
 gdb-port/utility-commands.py | 31 +++++++++++++++++--------------
 3 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/gdb-port/README.md b/gdb-port/README.md
index 18da846..c7ba895 100644
--- a/gdb-port/README.md
+++ b/gdb-port/README.md
@@ -78,6 +78,16 @@ hammer-parse-continue
 
 Alias of GDB `continue`. May change later.
 
+```
+hammer-parse-apply
+```
+
+Applies the current parser and prints the HParseResult. More precisely:
+
+Steps execution until the "current" parser (the one `h_do_parse()` has been called on at the time of command execution) returns its result. Thereafter, it steps to the next invocation of `h_do_parse`, and optionally prints the parser stack and input preview, as with `hammer-parse-step`.
+
+In terms of call stack navigation, this is roughly analogous to executing `finish` to step out of the current stack frame, followed by stepping into the next function call. (With the difference, that this commands steps between "frames" of the parser stack)
+
 ## Querying
 
 ```
diff --git a/gdb-port/commands.py b/gdb-port/commands.py
index e0668ff..c8b625a 100644
--- a/gdb-port/commands.py
+++ b/gdb-port/commands.py
@@ -209,7 +209,7 @@ class HammerParserPrintAST(gdb.Command):
 HammerParserPrintAST()
 
 # Step until the "current" parser is applied and returns the HParsedToken, stopping in h_do_parse
-class HammerParseApply(gdb.Command):
+class HammerParseApply(FlowControlWithPrint):
 	def __init__(self):
 		super(HammerParseApply, self).__init__("hammer-parse-apply", gdb.COMMAND_OBSCURE)
 		print(":: hammer-parse-apply")
@@ -224,16 +224,6 @@ class HammerParseApply(gdb.Command):
 		gdb.set_convenience_variable("hammer_step_counter", 1)
 		# Continue and stop at the next h_do_parse invocation
 		gdb.execute("continue")
-		try:
-			if gdb.parameter("hammer-extended-parse-step-info"):
-				print("Parser stack:")
-				gdb.execute("hammer-parser-backtrace")
-				print("Input preview:")
-				gdb.execute("hammer-parser-preview-input")
-		except RuntimeError as e:
-			# This probably means parser-name-instrumentation.py is not loaded.
-			#pass
-			print("Exception: %s" % e)
-			print("Probably caused by hammer-extended-parse-step-info parameter not existing")
+		self.conditionally_print_backtrace()
 
 HammerParseApply()
diff --git a/gdb-port/utility-commands.py b/gdb-port/utility-commands.py
index ae02fba..30bb43e 100644
--- a/gdb-port/utility-commands.py
+++ b/gdb-port/utility-commands.py
@@ -13,8 +13,23 @@ class HammerParseStopAtInputPos(gdb.Command):
 
 HammerParseStopAtInputPos()
 
+# __init__ deliberately omitted, because this is not actually a command we want to register, just inherit from
+class FlowControlWithPrint(gdb.Command):
+	def conditionally_print_backtrace(self):
+		try:
+			if gdb.parameter("hammer-extended-parse-step-info"):
+				print("Parser stack:")
+				gdb.execute("hammer-parser-backtrace")
+				print("Input preview:")
+				gdb.execute("hammer-parser-preview-input")
+		except RuntimeError as e:
+			# This probably means parser-name-instrumentation.py is not loaded.
+			#pass
+			print("Exception: %s" % e)
+			print("Probably caused by hammer-extended-parse-step-info parameter not existing")
+
 # Implements the "step" command for parsing. One step is one invocation of h_do_parse()
-class HammerParseStep(gdb.Command):
+class HammerParseStep(FlowControlWithPrint):
 	def __init__(self):
 		super(HammerParseStep, self).__init__ ("hammer-parse-step", gdb.COMMAND_OBSCURE)
 		print(":: hammer-parse-stop")
@@ -47,19 +62,7 @@ class HammerParseStep(gdb.Command):
 		if gdb.selected_inferior().pid > 0:
 			gdb.execute("continue")
 
-		# These are defined in parser-name-instrumentation.py, which we load after this, but this should be fine at runtime
-		# TODO: factor out commands into their own file
-		try:
-			if gdb.parameter("hammer-extended-parse-step-info"):
-				print("Parser stack:")
-				gdb.execute("hammer-parser-backtrace")
-				print("Input preview:")
-				gdb.execute("hammer-parser-preview-input")
-		except RuntimeError as e:
-			# This probably means parser-name-instrumentation.py is not loaded.
-			#pass
-			print("Exception: %s" % e)
-			print("Probably caused by hammer-extended-parse-step-info parameter not existing")
+		self.conditionally_print_backtrace()
 
 HammerParseStep()
 
-- 
GitLab