Code.require_file("tpl.exs") defmodule TplJson do # --- JSON Transpiler --- # transforms sexps into lists # braces into objects # tokens and strings into strings def to_json(ast) do ast |> Enum.map(&to_json_item/1) |> IO.inspect(label: "AST for JSON") # if the top level is a single elem, we output that directly |> case do [[single]] -> single [single] -> single multiple -> multiple end |> Jason.encode!(pretty: true) end defp to_json_item(%{t: :sexp, list: list}) do list |> Enum.map(&to_json_item/1) end defp to_json_item(%{t: :brace, list: list}) do list |> Enum.map(fn %{t: :sexp, list: [key_item | value_list]} -> key = to_json_item(key_item) value = case value_list do [ex] -> to_json_item(ex) _ -> value_list |> Enum.map(&to_json_item/1) end {key, value} end) |> Enum.into(%{}) end defp to_json_item(%{t: :token, str: str}), do: str defp to_json_item(%{t: :string, chunks: chunks, values: values}) do # For simplicity, concatenate chunks and ignore interpolations Enum.join(chunks) end end json_output = """ { asd "something else " nested { a ( b c asd asd asd) d e f inner { x y z } } """ |> Tpl.to_ast() |> TplJson.to_json() IO.puts("\n--- Generated JSON Output ---") IO.puts(json_output)