Add an s-exp renderer to pkl:syntax (#1955)

This commit is contained in:
Islon Scherer authored and GitHub committed 2026-11-05 17:10:33 +00:00
1 parent 85b4a4669a
commit fc5d658aa3
3 files changed
+223

No files matched your search

+65
View File
@@ -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