using System; using System.IO; using Finn.AST; namespace Finn; class ASTPrinter : IVisitor { public string print(Expr expr) { return expr.accept(this); } private string parenthesize(string name, params Expr[] exprs) { var w = new StringWriter(); w.Write($"({name}"); foreach (Expr expr in exprs) { w.Write(" "); w.Write(expr.accept(this)); } w.Write(")"); return w.ToString(); } public string visitBinaryExpr(Binary expr) { return parenthesize(expr.Op.lexeme, expr.Left, expr.Right); } public string visitGroupingExpr(Grouping expr) { return parenthesize("group", expr.Expression); } public string visitLiteralExpr(Literal expr) { return expr.Value.ToString() ?? ""; } private string formatName(Name name) { if (name.Quoted) return $"@\"{name.Value}\""; return name.Value; } public string visitIdentifierExpr(Identifier expr) { return formatName(expr.Value); } public string visitUnaryExpr(Unary expr) { return parenthesize(expr.Op.lexeme, expr.Right); } public string visitIfExpr(If expr) { return parenthesize("if", expr.Condition, expr.Then, expr.Else); } public string visitSequenceExpr(Sequence expr) { return parenthesize("seq", expr.Left, expr.Right); } public string visitSelectorExpr(Selector expr) { return parenthesize(".", expr.Left, new Identifier { Value = expr.FieldName }); } public string visitListExpr(List expr) { return parenthesize("list", expr.Elements); } public string visitVariantExpr(Variant expr) { if (expr.Argument == null) { return parenthesize("variant", new Identifier { Value = expr.Tag }); } return parenthesize("variant", new Identifier { Value = expr.Tag }, expr.Argument); } }