-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added ConsolePrettyPrinter debug frontend
- Loading branch information
Showing
2 changed files
with
102 additions
and
0 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
parsley-debug/shared/src/main/scala/parsley/debugger/frontend/ConsolePrettyPrinter.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright 2020 Parsley Contributors <https://github.com/j-mie6/Parsley/graphs/contributors> | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
package parsley.debugger.frontend | ||
|
||
import parsley.debugger.DebugTree | ||
import parsley.debugger.frontend.internal.consolepretty.* | ||
|
||
private [frontend] sealed class ConsolePrettyPrinterImpl private[frontend] (ioF: String => Unit) extends ReusableFrontend { | ||
override protected def processImpl(input: => String, tree: => DebugTree): Unit = { | ||
ioF(s"${tree.parserName}'s parse tree for input:\n\n$input\n\n") | ||
ioF(tree.pretty + "\n") | ||
} | ||
} | ||
|
||
/** A console pretty-printer for the debugger. | ||
* | ||
* It is recommended that all memory-heavy types (e.g. closures) are not stored explicitly. Consult the documentation | ||
* on attaching debuggers to find out how to prevent that. | ||
* | ||
* @since 5.0.0 | ||
*/ | ||
object ConsolePrettyPrinter extends ConsolePrettyPrinterImpl(println(_)) { | ||
/** Create a string pretty-printer that takes an arbitrary impure string function. | ||
* | ||
* @since 5.0.0 | ||
*/ | ||
def apply(ioF: String => Unit): ReusableFrontend = new ConsolePrettyPrinterImpl(ioF) | ||
} |
71 changes: 71 additions & 0 deletions
71
parsley-debug/shared/src/main/scala/parsley/debugger/frontend/internal/consolepretty.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright 2020 Parsley Contributors <https://github.com/j-mie6/Parsley/graphs/contributors> | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
package parsley.debugger.frontend.internal | ||
|
||
import scala.annotation.tailrec | ||
import scala.collection.mutable | ||
|
||
import parsley.debugger.{DebugTree, ParseAttempt} | ||
|
||
object consolepretty { | ||
// Utility class for aiding in the toString method for debug trees. | ||
private [frontend] case class PrettyPrintHelper(acc: mutable.StringBuilder, indents: Vector[String]) { | ||
// Indent a string with the given indenting delimiters. | ||
def bury(str: String, withMark: Boolean = true): Unit = { | ||
val pretty = | ||
if (indents.isEmpty) str | ||
else if (withMark) indents.init.mkString + "+-" + str | ||
else indents.mkString + str | ||
|
||
acc.append(pretty + "\n") | ||
} | ||
|
||
// Add a new indent delimiter to the current helper instance. | ||
// The accumulator is shared between new instances. | ||
def addIndent: PrettyPrintHelper = PrettyPrintHelper(acc, indents :+ "| ") | ||
|
||
// Adds a two-blank-space indent instead for the last child of a node. | ||
def addBlankIndent: PrettyPrintHelper = PrettyPrintHelper(acc, indents :+ " ") | ||
} | ||
|
||
implicit final class TreePrinter(val dt: DebugTree) extends AnyVal { | ||
def pretty: String = { | ||
val acc = new mutable.StringBuilder | ||
prettyPrint(PrettyPrintHelper(acc, Vector.empty)) | ||
acc.init.toString | ||
} | ||
|
||
private [TreePrinter] def prettyPrint(helper: PrettyPrintHelper): Unit = { | ||
val uname = | ||
if (dt.parserName != dt.internalName) | ||
s"${dt.parserName} (${dt.internalName}${if (dt.childNumber.isDefined) s" (${dt.childNumber.get})" else ""})" | ||
else | ||
s"${dt.internalName}${if (dt.childNumber.isDefined) s" (${dt.childNumber.get})" else ""}" | ||
val results = dt.parseResults.map(printParseAttempt).mkString | ||
|
||
helper.bury(s"[ $uname ]: $results") | ||
printChildren(helper, dt.nodeChildren.toList) | ||
} | ||
|
||
// Print a parse attempt in a human-readable way. | ||
private [TreePrinter] def printParseAttempt(attempt: ParseAttempt): String = | ||
s"(\"${attempt.rawInput}\" [${attempt.fromPos} -> ${attempt.toPos}], ${if (attempt.success) | ||
s"Success - [ ${attempt.result.get} ]" | ||
else "Failure"})" | ||
|
||
// Print all the children, remembering to add a blank indent for the last child. | ||
@tailrec private def printChildren(helper: PrettyPrintHelper, children: List[(String, DebugTree)]): Unit = children match { | ||
case (_, t) :: Nil => | ||
helper.bury("|", withMark = false) | ||
t.prettyPrint(helper.addBlankIndent) | ||
case (_, t) :: xs => | ||
helper.bury("|", withMark = false) | ||
t.prettyPrint(helper.addIndent) | ||
printChildren(helper, xs) | ||
case Nil => | ||
} | ||
} | ||
} |