diff --git a/gdb-port/README.md b/gdb-port/README.md
index cc3c6514d1fa6efc53ea2f65f848740e6163cfa2..6c28621777ec162ac61bf1b3533e8fc415104dc0 100644
--- a/gdb-port/README.md
+++ b/gdb-port/README.md
@@ -88,6 +88,17 @@ Steps execution until the "current" parser (the one `h_do_parse()` has been call
 
 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)
 
+Fair warning, this can get *really* slow with parsers that consume a few bytes at a time. (For example, filters in the pdf parser)
+
+```
+hammer-parse-apply-and-show-ast
+```
+
+Same as `hammer-parse-apply`, except once the AST is obtained, the boundaries of the tokens comprising the AST will be graphically displayed.
+
+Similar to the previous command, this can also get really slow under the same conditions.
+
+
 ```
 hammer-parse-step-to-result <number>
 ```
diff --git a/gdb-port/commands.py b/gdb-port/commands.py
index a57b68403a6d776791c73b3c91f9bdce8ba1a8b7..bcb548f52d303f475f2c7b29a9845f0ab3e84a75 100644
--- a/gdb-port/commands.py
+++ b/gdb-port/commands.py
@@ -221,6 +221,34 @@ class HammerParseApply(FlowControlWithPrint):
 		super(HammerParseApply, self).__init__("hammer-parse-apply", gdb.COMMAND_OBSCURE)
 		print(":: hammer-parse-apply")
 
+	def invoke(self, arg, from_tty):
+		#profiler = cProfile.Profile() # DEBUG
+		#profiler.enable() # DEBUG
+		with cProfile.Profile() as profiler: # DEBUG
+			#top_level_parse.setup_ast_stack_index(0) #TODO: is it a problem if this command overwrites it? would it better to use a convenience variable, as with parse-step?
+
+			# HDoParseRetBreakpoint sets hammer_step_counter to 1 after capturing the AST subtree, so this will stop at the first h_do_parse invocation afterwards
+			if gdb.selected_inferior().pid > 0:
+				gdb.execute("continue")
+
+			#top_level_parse.clear_ast_stack_index()
+
+			self.conditionally_print_backtrace()
+		profiler.print_stats(sort='tottime') # DEBUG
+		#profiler.disable() # DEBUG
+		#s = io.StringIO() # DEBUG
+		#sortby = SortKey.CUMULATIVE # DEBUG
+		#ps = pstats.Stats(pr, stream=s).sort_stats(sortby) # DEBUG
+		#ps.print_stats() # DEBUG
+		#print(s.getvalue()) # DEBUG
+
+HammerParseApply()
+
+class HammerParseApplyAndShowAST(FlowControlWithPrint):
+	def __init__(self):
+		super(HammerParseApplyAndShowAST, self).__init__("hammer-parse-apply-and-show-ast", gdb.COMMAND_OBSCURE)
+		print(":: hammer-parse-apply-and-show-ast")
+
 	def invoke(self, arg, from_tty):
 		#profiler = cProfile.Profile() # DEBUG
 		#profiler.enable() # DEBUG
@@ -242,4 +270,4 @@ class HammerParseApply(FlowControlWithPrint):
 		#ps.print_stats() # DEBUG
 		#print(s.getvalue()) # DEBUG
 
-HammerParseApply()
+HammerParseApplyAndShowAST()
diff --git a/gdb-port/startup_scripts/shell.sh b/gdb-port/startup_scripts/shell.sh
index e32a9582741b9228d7952bef9269849b0c1a861e..ecf92014a4412f5858c34f23d6274ea283b7692c 100755
--- a/gdb-port/startup_scripts/shell.sh
+++ b/gdb-port/startup_scripts/shell.sh
@@ -2,7 +2,7 @@
 
 gdb -ex "set python print-stack full" -ex "source perf-instrumentation/gdb-port/parser.py" -ex "source perf-instrumentation/gdb-port/utility-commands.py" -ex "source perf-instrumentation/gdb-port/commands.py" -ex "source perf-instrumentation/gdb-port/hammer-breakpoints.py" -ex "source perf-instrumentation/gdb-port/ast.py" -ex "source perf-instrumentation/gdb-port/breakpoint-manager.py" -ex "source perf-instrumentation/gdb-port/top-level-parse.py" -ex "hammer-parse-stop-at-pos 50" -ex "source perf-instrumentation/gdb-port/parser-type-instrumentation-gdb.py" -ex "source perf-instrumentation/gdb-port/parser-name-instrumentation-gdb.py" \
 -ex "hammer-parse-step 7" \
--ex "python [gdb.execute('hammer-parse-apply') for x in range(8)]" \
+-ex "python [gdb.execute('hammer-parse-apply-and-show-ast') for x in range(8)]" \
 --args pdf t/000143.pdf
 
 # hammer-parse-step 7 is arbitrary, but happens to get to a location in the file that's convenient for testing token printing