diff --git a/src/chalk/print_visitor.cr b/src/chalk/print_visitor.cr new file mode 100644 index 0000000..91fec2b --- /dev/null +++ b/src/chalk/print_visitor.cr @@ -0,0 +1,68 @@ +require "./tree.cr" + +module Chalk + class PrintVisitor < Visitor + def initialize + @indent = 0 + end + + def print_indent + @indent.times do + STDOUT << " " + end + end + + def visit(id : TreeId) + print_indent + puts id.id + end + + def visit(lit : TreeLit) + print_indent + puts lit.lit + end + + def visit(op : TreeOp) + print_indent + STDOUT << "[op] " + puts op.op + @indent += 1 + end + + def finish(op : TreeOp) + @indent -= 1 + end + + def visit(function : TreeFunction) + print_indent + STDOUT << "[function] " << function.name << "( " + function.params.each do |param| + STDOUT << param << " " + end + puts ")" + @indent += 1 + end + + def finish(function : TreeFunction) + @indent -= 1 + end + + macro forward(text, type) + def visit(tree : {{type}}) + print_indent + puts {{text}} + @indent += 1 + end + + def finish(tree : {{type}}) + @indent -= 1 + end + end + + forward("[block]", TreeBlock) + forward("[var]", TreeVar) + forward("[if]", TreeIf) + forward("[while]", TreeWhile) + forward("[return]", TreeReturn) + end +end diff --git a/src/chalk/tree.cr b/src/chalk/tree.cr new file mode 100644 index 0000000..919c76f --- /dev/null +++ b/src/chalk/tree.cr @@ -0,0 +1,114 @@ +module Chalk + class Visitor + def visit(tree : Tree) + end + + def finish(tree : Tree) + end + end + + class Tree + def accept(v : Visitor) + v.visit(self) + v.finish(self) + end + end + + class TreeId < Tree + property id : String + def initialize(@id : String) end + end + + class TreeLit < Tree + property lit : Int64 + def initialize(@lit : Int64) end + end + + class TreeOp < Tree + property op : TokenType + property left : Tree + property right : Tree + def initialize(@op : TokenType, @left : Tree, @right : Tree) end + + def accept(v : Visitor) + v.visit(self) + @left.accept(v) + @right.accept(v) + v.finish(self) + end + end + + class TreeBlock < Tree + def initialize(@children : Array(Tree)) end + + def accept(v : Visitor) + v.visit(self) + @children.each &.accept(v) + v.finish(self) + end + end + + class TreeFunction < Tree + property name : String + property params : Array(String) + property block : Tree + + def initialize(@name : String, @params : Array(String), @block : Tree) end + def accept(v : Visitor) + v.visit(self) + @block.accept(v) + v.finish(self) + end + end + + class TreeVar < Tree + property name : String + property expr : Tree + + def initialize(@name : String, @expr : Tree) end + def accept(v : Visitor) + v.visit(self) + @expr.accept(v) + v.finish(self) + end + end + + class TreeIf < Tree + property condition : Tree + property block : Tree + property otherwise : Tree + + def initialize(@condition : Tree, @block : Tree, @otherwise : Tree) end + def accept(v : Visitor) + v.visit(self) + @condition.accept(v) + @block.accept(v) + @otherwise.accept(v) + v.finish(self) + end + end + + class TreeWhile < Tree + property condition : Tree + property block : Tree + + def initialize(@condition : Tree, @block : Tree) end + def accept(v : Visitor) + v.visit(self) + @condition.accept(v) + @block.accept(v) + v.finish(self) + end + end + + class TreeReturn < Tree + property rvalue : Tree + + def initialize(@rvalue : Tree) end + def accept(v : Visitor) + v.visit(self) + @rvalue.accept(v) + v.finish(self) + end + end +end