Add an s-exp renderer to pkl:syntax (#1955)
This commit is contained in:
1 parent
85b4a4669a
commit
fc5d658aa3
3 files changed
+223
No files matched your search
@@ -49,6 +49,71 @@ class FormattingRenderer {
|
||||
external function renderValue(node: Node): String
|
||||
}
|
||||
|
||||
/// Renders a [Node] as an [S-expression](https://en.wikipedia.org/wiki/S-expression).
|
||||
///
|
||||
/// Each node is rendered as its [type][Node.type] in parentheses, followed by its
|
||||
/// [children][Node.children], each on its own line and indented by two spaces.
|
||||
/// Nodes without children are rendered on a single line.
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// new SExpressionRenderer {}.renderValue(new Parser {}.parseExpression("1 + 2"))
|
||||
/// ```
|
||||
///
|
||||
/// The above renders:
|
||||
///
|
||||
/// ```
|
||||
/// (binary_op_expr
|
||||
/// (int_literal_expr "1")
|
||||
/// (operator "+")
|
||||
/// (int_literal_expr "2"))
|
||||
/// ```
|
||||
class SExpressionRenderer {
|
||||
/// Whether to render the [Node.text] of terminal nodes whose text is not implied by their
|
||||
/// [Node.type].
|
||||
///
|
||||
/// If [true], the text follows the type as a quoted, escaped string, as in
|
||||
/// `(int_literal_expr "5")`.
|
||||
/// If [false], only the type is rendered.
|
||||
renderTerminalText: Boolean = true
|
||||
|
||||
/// The types of the terminal nodes that [renderTerminalText] applies to.
|
||||
local textTypes: Set<TerminalNodeType> =
|
||||
Set(
|
||||
"identifier",
|
||||
"modifier",
|
||||
"operator",
|
||||
"bool_literal_expr",
|
||||
"int_literal_expr",
|
||||
"float_literal_expr",
|
||||
"string_start",
|
||||
"string_multi_start",
|
||||
"string_end",
|
||||
"interpolation_start",
|
||||
"string_chars",
|
||||
"string_escape",
|
||||
"string_continuation",
|
||||
"shebang",
|
||||
"line_comment",
|
||||
"block_comment",
|
||||
"doc_comment_line",
|
||||
)
|
||||
|
||||
/// Renders [value] as a S-expression.
|
||||
function renderValue(value: Node): String = renderIndented(value, "")
|
||||
|
||||
local function renderIndented(node: Node, indent: String): String =
|
||||
if (node.children.isEmpty)
|
||||
if (renderTerminalText && textTypes.contains(node.type))
|
||||
"\(indent)(\(node.type) \(new PcfRenderer {}.renderValue(node.text)))"
|
||||
else
|
||||
"\(indent)(\(node.type))"
|
||||
else
|
||||
"\(indent)(\(node.type)\n"
|
||||
+ node.children.map((child) -> renderIndented(child, indent + " ")).join("\n")
|
||||
+ ")"
|
||||
}
|
||||
|
||||
/// A generic, untyped node in the Pkl syntax tree.
|
||||
///
|
||||
/// A node is either a *leaf*, carrying no [children], or a *branch*, whose content is its
|
||||
|
||||
Reference in new issue
Block a user