Run the format tool.

This commit is contained in:
Danila Fedorin 2018-07-25 13:53:35 -07:00
parent fa00bda8ab
commit df2a00fd66
7 changed files with 570 additions and 551 deletions

View File

@ -1,12 +1,12 @@
require "./chalk/*"
module Chalk
lexer = Lexer.new
parser = Parser.new
lexer = Lexer.new
parser = Parser.new
tokens = lexer.lex(File.read("test.txt"))
trees = parser.parse?(tokens)
trees.try do |trees|
trees.each &.accept(PrintVisitor.new)
end
tokens = lexer.lex(File.read("test.txt"))
trees = parser.parse?(tokens)
trees.try do |trees|
trees.each &.accept(PrintVisitor.new)
end
end

View File

@ -2,37 +2,37 @@ require "./lexer.cr"
require "./parsers.cr"
module Chalk
module Builder
def type(type): BasicParser(Token)
return TypeParser.new(type).as(BasicParser(Token))
end
def char(type): BasicParser(Token)
return CharParser.new(type).as(BasicParser(Token))
end
def transform(parser : BasicParser(T), &transform : T -> R) forall T, R
return TransformParser.new(parser, &transform).as(BasicParser(R))
end
def optional(parser : BasicParser(T)): BasicParser(T?) forall T
return OptionalParser.new(parser).as(BasicParser(T?))
end
def either(*args : BasicParser(T)): BasicParser(T) forall T
return EitherParser.new(args.to_a).as(BasicParser(T))
end
def many(parser : BasicParser(T)): BasicParser(Array(T)) forall T
return ManyParser.new(parser).as(BasicParser(Array(T)))
end
def delimited(parser : BasicParser(T), delimiter : BasicParser(R)): BasicParser(Array(T)) forall T, R
return DelimitedParser.new(parser, delimiter).as(BasicParser(Array(T)))
end
def then(first : BasicParser(T), second : BasicParser(R)) forall T, R
return NextParser.new(first, second).as(BasicParser(Array(T | R)))
end
module Builder
def type(type) : BasicParser(Token)
return TypeParser.new(type).as(BasicParser(Token))
end
def char(type) : BasicParser(Token)
return CharParser.new(type).as(BasicParser(Token))
end
def transform(parser : BasicParser(T), &transform : T -> R) forall T, R
return TransformParser.new(parser, &transform).as(BasicParser(R))
end
def optional(parser : BasicParser(T)) : BasicParser(T?) forall T
return OptionalParser.new(parser).as(BasicParser(T?))
end
def either(*args : BasicParser(T)) : BasicParser(T) forall T
return EitherParser.new(args.to_a).as(BasicParser(T))
end
def many(parser : BasicParser(T)) : BasicParser(Array(T)) forall T
return ManyParser.new(parser).as(BasicParser(Array(T)))
end
def delimited(parser : BasicParser(T), delimiter : BasicParser(R)) : BasicParser(Array(T)) forall T, R
return DelimitedParser.new(parser, delimiter).as(BasicParser(Array(T)))
end
def then(first : BasicParser(T), second : BasicParser(R)) forall T, R
return NextParser.new(first, second).as(BasicParser(Array(T | R)))
end
end
end

View File

@ -1,82 +1,82 @@
require "lex"
module Chalk
enum TokenType
Any,
Str,
Id,
LitDec,
LitBin,
LitHex,
OpAdd
OpSub
OpMul
OpDiv
OpOr
OpAnd
OpXor
KwSprite
KwInline
KwFun
KwU0
KwU8
KwU12
KwVar
KwIf
KwElse
KwWhile
KwReturn
enum TokenType
Any,
Str,
Id,
LitDec,
LitBin,
LitHex,
OpAdd
OpSub
OpMul
OpDiv
OpOr
OpAnd
OpXor
KwSprite
KwInline
KwFun
KwU0
KwU8
KwU12
KwVar
KwIf
KwElse
KwWhile
KwReturn
end
class Token
def initialize(@string : String, @type : TokenType)
end
class Token
def initialize(@string : String, @type : TokenType)
end
getter string : String
getter type : TokenType
end
getter string : String
getter type : TokenType
class Lexer
def initialize
@lexer = Lex::Lexer.new
@lexer.add_pattern(".", TokenType::Any.value)
@lexer.add_pattern("\"(\\\\\"|[^\"])*\"",
TokenType::Str.value)
@lexer.add_pattern("[a-zA-Z_][a-zA-Z_0-9]*",
TokenType::Id.value)
@lexer.add_pattern("[0-9]+",
TokenType::LitDec.value)
@lexer.add_pattern("0b[0-1]+",
TokenType::LitBin.value)
@lexer.add_pattern("0x[0-9a-fA-F]+",
TokenType::LitHex.value)
@lexer.add_pattern("\\+", TokenType::OpAdd.value)
@lexer.add_pattern("-", TokenType::OpSub.value)
@lexer.add_pattern("\\*", TokenType::OpMul.value)
@lexer.add_pattern("/", TokenType::OpDiv.value)
@lexer.add_pattern("&", TokenType::OpAdd.value)
@lexer.add_pattern("\\|", TokenType::OpOr.value)
@lexer.add_pattern("^", TokenType::OpXor.value)
@lexer.add_pattern("sprite", TokenType::KwSprite.value)
@lexer.add_pattern("inline", TokenType::KwInline.value)
@lexer.add_pattern("fun", TokenType::KwFun.value)
@lexer.add_pattern("u0", TokenType::KwU0.value)
@lexer.add_pattern("u8", TokenType::KwU8.value)
@lexer.add_pattern("u12", TokenType::KwU12.value)
@lexer.add_pattern("var", TokenType::KwVar.value)
@lexer.add_pattern("if", TokenType::KwIf.value)
@lexer.add_pattern("else", TokenType::KwElse.value)
@lexer.add_pattern("while", TokenType::KwWhile.value)
@lexer.add_pattern("return", TokenType::KwReturn.value)
end
class Lexer
def initialize
@lexer = Lex::Lexer.new
@lexer.add_pattern(".", TokenType::Any.value)
@lexer.add_pattern("\"(\\\\\"|[^\"])*\"",
TokenType::Str.value)
@lexer.add_pattern("[a-zA-Z_][a-zA-Z_0-9]*",
TokenType::Id.value)
@lexer.add_pattern("[0-9]+",
TokenType::LitDec.value)
@lexer.add_pattern("0b[0-1]+",
TokenType::LitBin.value)
@lexer.add_pattern("0x[0-9a-fA-F]+",
TokenType::LitHex.value)
@lexer.add_pattern("\\+", TokenType::OpAdd.value)
@lexer.add_pattern("-", TokenType::OpSub.value)
@lexer.add_pattern("\\*", TokenType::OpMul.value)
@lexer.add_pattern("/", TokenType::OpDiv.value)
@lexer.add_pattern("&", TokenType::OpAdd.value)
@lexer.add_pattern("\\|", TokenType::OpOr.value)
@lexer.add_pattern("^", TokenType::OpXor.value)
@lexer.add_pattern("sprite", TokenType::KwSprite.value)
@lexer.add_pattern("inline", TokenType::KwInline.value)
@lexer.add_pattern("fun", TokenType::KwFun.value)
@lexer.add_pattern("u0", TokenType::KwU0.value)
@lexer.add_pattern("u8", TokenType::KwU8.value)
@lexer.add_pattern("u12", TokenType::KwU12.value)
@lexer.add_pattern("var", TokenType::KwVar.value)
@lexer.add_pattern("if", TokenType::KwIf.value)
@lexer.add_pattern("else", TokenType::KwElse.value)
@lexer.add_pattern("while", TokenType::KwWhile.value)
@lexer.add_pattern("return", TokenType::KwReturn.value)
end
def lex(string)
return @lexer.lex(string)
.select { |t| !t[0][0].whitespace? }
.map do |tuple|
string, id = tuple
Token.new(string, TokenType.new(id))
end
def lex(string)
return @lexer.lex(string)
.select { |t| !t[0][0].whitespace? }
.map do |tuple|
string, id = tuple
Token.new(string, TokenType.new(id))
end
end
end
end

View File

@ -1,173 +1,173 @@
require "./builder.cr"
module Chalk
class Parser
include Builder
class Parser
include Builder
private def create_type
either(type(TokenType::KwU0), type(TokenType::KwU8), type(TokenType::KwU12))
end
private def create_lit
dec_parser = type(TokenType::LitDec).transform &.string.to_i64
hex_parser = type(TokenType::LitHex).transform &.string.lchop("0x").to_i64(16)
bin_parser = type(TokenType::LitBin).transform &.string.lchop("0b").to_i64(2)
lit_parser = either(dec_parser, hex_parser, bin_parser).transform { |it| TreeLit.new(it).as(Tree) }
return lit_parser
end
private def create_op_expr(atom, op)
pl = PlaceholderParser(Tree).new
recurse = atom.then(op).then(pl).transform do |arr|
arr = arr.flatten
TreeOp.new(
arr[1].as(Token).type,
arr[0].as(Tree),
arr[2].as(Tree)).as(Tree)
end
pl.parser = either(recurse, atom)
return pl
end
private def create_op_exprs(atom, ops)
ops.reduce(atom) do |previous, current|
create_op_expr(previous, current)
end
end
private def create_call(expr)
call = type(TokenType::Id).then(char '(').then(delimited(expr, char ',')).then(char ')').transform do |arr|
arr = arr.flatten
name = arr[0].as(Token).string
params = arr[2..arr.size - 2].map &.as(Tree)
TreeCall.new(name, params).as(Tree)
end
return call
end
private def create_expr
expr_place = PlaceholderParser(Tree).new
literal = create_lit
id = type(TokenType::Id).transform { |it| TreeId.new(it.string).as(Tree) }
call = create_call(expr_place)
atom = either(literal, call, id)
ops = [ either(type(TokenType::OpMul), type(TokenType::OpDiv)),
either(type(TokenType::OpAdd), type(TokenType::OpSub)),
type(TokenType::OpXor),
type(TokenType::OpAnd),
type(TokenType::OpOr) ]
expr = create_op_exprs(atom, ops)
expr_place.parser = expr
return expr
end
private def create_var(expr)
var = type(TokenType::KwVar).then(type(TokenType::Id)).then(char '=').then(expr).then(char ';').transform do |arr|
arr = arr.flatten
name = arr[1].as(Token).string
exp = arr[arr.size - 2].as(Tree)
TreeVar.new(name, exp).as(Tree)
end
return var
end
private def create_assign(expr)
assign = type(TokenType::Id).then(char '=').then(expr).then(char ';').transform do |arr|
arr = arr.flatten
name = arr[0].as(Token).string
exp = arr[arr.size - 2].as(Tree)
TreeAssign.new(name, exp).as(Tree)
end
return assign
end
private def create_basic(expr)
basic = expr.then(char ';').transform do |arr|
arr.flatten[0].as(Tree)
end
return basic
end
private def create_if(expr, block)
iff = type(TokenType::KwIf).then(char '(').then(expr).then(char ')').then(block)
.then(optional(type(TokenType::KwElse).then(block)))
.transform do |arr|
arr = arr.flatten
cond = arr[2].as(Tree)
code = arr[4].as(Tree)
otherwise = arr.size == 7 ? arr[6].as(Tree) : nil
TreeIf.new(cond, code, otherwise).as(Tree)
end
return iff
end
private def create_while(expr, block)
whilee = type(TokenType::KwWhile).then(char '(').then(expr).then(char ')').then(block).transform do |arr|
arr = arr.flatten
cond = arr[2].as(Tree)
code = arr[4].as(Tree)
TreeWhile.new(cond, code).as(Tree)
end
return whilee
end
private def create_return(expr)
returnn = type(TokenType::KwReturn).then(expr).then(char ';').transform do |arr|
arr = arr.flatten
value = arr[1].as(Tree)
TreeReturn.new(value).as(Tree)
end
return returnn
end
private def create_block(statement)
block = char('{').then(many(statement)).then(char '}').transform do |arr|
arr = arr.flatten
params = arr[1..arr.size - 2].map &.as(Tree)
TreeBlock.new(params).as(Tree)
end
return block
end
private def create_statement_block
statement_place = PlaceholderParser(Tree).new
expr = create_expr
block = create_block(statement_place)
iff = create_if(expr, block)
whilee = create_while(expr, block)
returnn = create_return(expr)
var = create_var(expr)
assign = create_assign(expr)
basic = create_basic(expr)
statement = either(basic, var, assign, block, iff, whilee, returnn)
statement_place.parser = statement
return {statement, block}
end
private def create_func(block, type)
func = type(TokenType::KwFun).then(type(TokenType::Id))
.then(char '(').then(delimited(type(TokenType::Id), char ',')).then(char ')')
.then(char ':').then(type)
.then(block).transform do |arr|
arr = arr.flatten
name = arr[1].as(Token).string
params = arr[3..arr.size - 5].map &.as(Token).string
code = arr[arr.size - 1].as(Tree)
type = arr[arr.size - 2].as(Token).type
TreeFunction.new(name, params, code).as(Tree)
end
return func
end
def initialize
_, block = create_statement_block
@parser = many(create_func(block, create_type)).as(BasicParser(Array(Tree)))
end
def parse?(tokens)
return @parser.parse?(tokens, 0).try &.[0]
end
private def create_type
either(type(TokenType::KwU0), type(TokenType::KwU8), type(TokenType::KwU12))
end
private def create_lit
dec_parser = type(TokenType::LitDec).transform &.string.to_i64
hex_parser = type(TokenType::LitHex).transform &.string.lchop("0x").to_i64(16)
bin_parser = type(TokenType::LitBin).transform &.string.lchop("0b").to_i64(2)
lit_parser = either(dec_parser, hex_parser, bin_parser).transform { |it| TreeLit.new(it).as(Tree) }
return lit_parser
end
private def create_op_expr(atom, op)
pl = PlaceholderParser(Tree).new
recurse = atom.then(op).then(pl).transform do |arr|
arr = arr.flatten
TreeOp.new(
arr[1].as(Token).type,
arr[0].as(Tree),
arr[2].as(Tree)).as(Tree)
end
pl.parser = either(recurse, atom)
return pl
end
private def create_op_exprs(atom, ops)
ops.reduce(atom) do |previous, current|
create_op_expr(previous, current)
end
end
private def create_call(expr)
call = type(TokenType::Id).then(char '(').then(delimited(expr, char ',')).then(char ')').transform do |arr|
arr = arr.flatten
name = arr[0].as(Token).string
params = arr[2..arr.size - 2].map &.as(Tree)
TreeCall.new(name, params).as(Tree)
end
return call
end
private def create_expr
expr_place = PlaceholderParser(Tree).new
literal = create_lit
id = type(TokenType::Id).transform { |it| TreeId.new(it.string).as(Tree) }
call = create_call(expr_place)
atom = either(literal, call, id)
ops = [either(type(TokenType::OpMul), type(TokenType::OpDiv)),
either(type(TokenType::OpAdd), type(TokenType::OpSub)),
type(TokenType::OpXor),
type(TokenType::OpAnd),
type(TokenType::OpOr)]
expr = create_op_exprs(atom, ops)
expr_place.parser = expr
return expr
end
private def create_var(expr)
var = type(TokenType::KwVar).then(type(TokenType::Id)).then(char '=').then(expr).then(char ';').transform do |arr|
arr = arr.flatten
name = arr[1].as(Token).string
exp = arr[arr.size - 2].as(Tree)
TreeVar.new(name, exp).as(Tree)
end
return var
end
private def create_assign(expr)
assign = type(TokenType::Id).then(char '=').then(expr).then(char ';').transform do |arr|
arr = arr.flatten
name = arr[0].as(Token).string
exp = arr[arr.size - 2].as(Tree)
TreeAssign.new(name, exp).as(Tree)
end
return assign
end
private def create_basic(expr)
basic = expr.then(char ';').transform do |arr|
arr.flatten[0].as(Tree)
end
return basic
end
private def create_if(expr, block)
iff = type(TokenType::KwIf).then(char '(').then(expr).then(char ')').then(block)
.then(optional(type(TokenType::KwElse).then(block)))
.transform do |arr|
arr = arr.flatten
cond = arr[2].as(Tree)
code = arr[4].as(Tree)
otherwise = arr.size == 7 ? arr[6].as(Tree) : nil
TreeIf.new(cond, code, otherwise).as(Tree)
end
return iff
end
private def create_while(expr, block)
whilee = type(TokenType::KwWhile).then(char '(').then(expr).then(char ')').then(block).transform do |arr|
arr = arr.flatten
cond = arr[2].as(Tree)
code = arr[4].as(Tree)
TreeWhile.new(cond, code).as(Tree)
end
return whilee
end
private def create_return(expr)
returnn = type(TokenType::KwReturn).then(expr).then(char ';').transform do |arr|
arr = arr.flatten
value = arr[1].as(Tree)
TreeReturn.new(value).as(Tree)
end
return returnn
end
private def create_block(statement)
block = char('{').then(many(statement)).then(char '}').transform do |arr|
arr = arr.flatten
params = arr[1..arr.size - 2].map &.as(Tree)
TreeBlock.new(params).as(Tree)
end
return block
end
private def create_statement_block
statement_place = PlaceholderParser(Tree).new
expr = create_expr
block = create_block(statement_place)
iff = create_if(expr, block)
whilee = create_while(expr, block)
returnn = create_return(expr)
var = create_var(expr)
assign = create_assign(expr)
basic = create_basic(expr)
statement = either(basic, var, assign, block, iff, whilee, returnn)
statement_place.parser = statement
return {statement, block}
end
private def create_func(block, type)
func = type(TokenType::KwFun).then(type(TokenType::Id))
.then(char '(').then(delimited(type(TokenType::Id), char ',')).then(char ')')
.then(char ':').then(type)
.then(block).transform do |arr|
arr = arr.flatten
name = arr[1].as(Token).string
params = arr[3..arr.size - 5].map &.as(Token).string
code = arr[arr.size - 1].as(Tree)
type = arr[arr.size - 2].as(Token).type
TreeFunction.new(name, params, code).as(Tree)
end
return func
end
def initialize
_, block = create_statement_block
@parser = many(create_func(block, create_type)).as(BasicParser(Array(Tree)))
end
def parse?(tokens)
return @parser.parse?(tokens, 0).try &.[0]
end
end
end

View File

@ -1,151 +1,149 @@
require "./builder.cr"
module Chalk
abstract class BasicParser(T)
abstract def parse?(tokens : Array(Token),
index : Int64) : Tuple(T, Int64)?
abstract class BasicParser(T)
abstract def parse?(tokens : Array(Token),
index : Int64): Tuple(T, Int64)?
def parse(tokens : Array(Token),
index : Int64): Tuple(T, Int64)
return parse?(tokens, index).not_nil!
end
def transform(&transform : T -> R) forall R
return TransformParser.new(self, &transform).as(BasicParser(R))
end
def then(other : BasicParser(R)): BasicParser(Array(T | R)) forall R
return NextParser
.new(self, other)
.as(BasicParser(Array(T | R)))
end
def parse(tokens : Array(Token),
index : Int64) : Tuple(T, Int64)
return parse?(tokens, index).not_nil!
end
class TypeParser < BasicParser(Token)
def initialize(@type : TokenType)
end
def parse?(tokens, index)
return nil unless index < tokens.size
return nil unless tokens[index].type == @type
return { tokens[index], index + 1}
end
def transform(&transform : T -> R) forall R
return TransformParser.new(self, &transform).as(BasicParser(R))
end
class CharParser < BasicParser(Token)
def initialize(@char : Char)
end
def then(other : BasicParser(R)) : BasicParser(Array(T | R)) forall R
return NextParser.new(self, other).as(BasicParser(Array(T | R)))
end
end
def parse?(tokens, index)
return nil unless index < tokens.size
return nil unless (tokens[index].type == TokenType::Any) &&
tokens[index].string[0] == @char
return { tokens[index], index + 1}
end
class TypeParser < BasicParser(Token)
def initialize(@type : TokenType)
end
class TransformParser(T, R) < BasicParser(R)
def initialize(@parser : BasicParser(T), &@block : T -> R)
end
def parse?(tokens, index)
return nil unless index < tokens.size
return nil unless tokens[index].type == @type
return {tokens[index], index + 1}
end
end
def parse?(tokens, index)
if parsed = @parser.parse?(tokens, index)
return { @block.call(parsed[0]), parsed[1] }
end
return nil
end
class CharParser < BasicParser(Token)
def initialize(@char : Char)
end
class OptionalParser(T) < BasicParser(T?)
def initialize(@parser : BasicParser(T))
end
def parse?(tokens, index)
return nil unless index < tokens.size
return nil unless (tokens[index].type == TokenType::Any) &&
tokens[index].string[0] == @char
return {tokens[index], index + 1}
end
end
def parse?(tokens, index)
if parsed = @parser.parse?(tokens, index)
return { parsed[0], parsed[1] }
end
return { nil, index }
end
class TransformParser(T, R) < BasicParser(R)
def initialize(@parser : BasicParser(T), &@block : T -> R)
end
class EitherParser(T) < BasicParser(T)
def initialize(@parsers : Array(BasicParser(T)))
end
def parse?(tokens, index)
if parsed = @parser.parse?(tokens, index)
return {@block.call(parsed[0]), parsed[1]}
end
return nil
end
end
def parse?(tokens, index)
@parsers.each do |parser|
if parsed = parser.parse?(tokens, index)
return parsed
end
end
return nil
end
class OptionalParser(T) < BasicParser(T?)
def initialize(@parser : BasicParser(T))
end
class ManyParser(T) < BasicParser(Array(T))
def initialize(@parser : BasicParser(T))
end
def parse?(tokens, index)
if parsed = @parser.parse?(tokens, index)
return {parsed[0], parsed[1]}
end
return {nil, index}
end
end
def parse?(tokens, index)
many = [] of T
while parsed = @parser.parse?(tokens, index)
item, index = parsed
many << item
end
return { many, index }
end
class EitherParser(T) < BasicParser(T)
def initialize(@parsers : Array(BasicParser(T)))
end
class DelimitedParser(T, R) < BasicParser(Array(T))
def initialize(@parser : BasicParser(T), @delimiter : BasicParser(R))
def parse?(tokens, index)
@parsers.each do |parser|
if parsed = parser.parse?(tokens, index)
return parsed
end
end
return nil
end
end
def parse?(tokens, index)
array = [] of T
first = @parser.parse?(tokens, index)
return { array, index } unless first
first_value, index = first
array << first_value
while delimiter = @delimiter.parse?(tokens, index)
_, new_index = delimiter
new = @parser.parse?(tokens, new_index)
break unless new
new_value, index = new
array << new_value
end
return { array, index }
end
class ManyParser(T) < BasicParser(Array(T))
def initialize(@parser : BasicParser(T))
end
class NextParser(T, R) < BasicParser(Array(T | R))
def initialize(@first : BasicParser(T), @second : BasicParser(R))
end
def parse?(tokens, index)
many = [] of T
while parsed = @parser.parse?(tokens, index)
item, index = parsed
many << item
end
return {many, index}
end
end
def parse?(tokens, index)
first = @first.parse?(tokens, index)
return nil unless first
first_value, index = first
second = @second.parse?(tokens, index)
return nil unless second
second_value, index = second
array = Array(T | R).new
array << first_value << second_value
return { array, index }
end
class DelimitedParser(T, R) < BasicParser(Array(T))
def initialize(@parser : BasicParser(T), @delimiter : BasicParser(R))
end
class PlaceholderParser(T) < BasicParser(T)
property parser : BasicParser(T)?
def parse?(tokens, index)
array = [] of T
first = @parser.parse?(tokens, index)
return {array, index} unless first
first_value, index = first
array << first_value
while delimiter = @delimiter.parse?(tokens, index)
_, new_index = delimiter
new = @parser.parse?(tokens, new_index)
break unless new
new_value, index = new
array << new_value
end
def initialize
@parser = nil
end
def parse?(tokens, index)
@parser.try &.parse?(tokens, index)
end
return {array, index}
end
end
class NextParser(T, R) < BasicParser(Array(T | R))
def initialize(@first : BasicParser(T), @second : BasicParser(R))
end
def parse?(tokens, index)
first = @first.parse?(tokens, index)
return nil unless first
first_value, index = first
second = @second.parse?(tokens, index)
return nil unless second
second_value, index = second
array = Array(T | R).new
array << first_value << second_value
return {array, index}
end
end
class PlaceholderParser(T) < BasicParser(T)
property parser : BasicParser(T)?
def initialize
@parser = nil
end
def parse?(tokens, index)
@parser.try &.parse?(tokens, index)
end
end
end

View File

@ -1,53 +1,53 @@
require "./tree.cr"
module Chalk
class PrintVisitor < Visitor
def initialize
@indent = 0
end
class PrintVisitor < Visitor
def initialize
@indent = 0
end
def print_indent
@indent.times do
STDOUT << " "
end
end
def print_indent
@indent.times do
STDOUT << " "
end
end
def visit(id : TreeId)
print_indent
puts id.id
end
def visit(id : TreeId)
print_indent
puts id.id
end
def visit(lit : TreeLit)
print_indent
puts lit.lit
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 visit(op : TreeOp)
print_indent
STDOUT << "[op] "
puts op.op
@indent += 1
end
def finish(op : TreeOp)
@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 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
def finish(function : TreeFunction)
@indent -= 1
end
macro forward(text, type)
macro forward(text, type)
def visit(tree : {{type}})
print_indent
puts {{text}}
@ -59,12 +59,12 @@ module Chalk
end
end
forward("[call]", TreeCall)
forward("[block]", TreeBlock)
forward("[var]", TreeVar)
forward("[assign]", TreeAssign)
forward("[if]", TreeIf)
forward("[while]", TreeWhile)
forward("[return]", TreeReturn)
end
forward("[call]", TreeCall)
forward("[block]", TreeBlock)
forward("[var]", TreeVar)
forward("[assign]", TreeAssign)
forward("[if]", TreeIf)
forward("[while]", TreeWhile)
forward("[return]", TreeReturn)
end
end

View File

@ -1,138 +1,159 @@
module Chalk
class Visitor
def visit(tree : Tree)
end
def finish(tree : Tree)
end
class Visitor
def visit(tree : Tree)
end
class Tree
def accept(v : Visitor)
v.visit(self)
v.finish(self)
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 TreeCall < Tree
property name : String
property params : Array(Tree)
def initialize(@name : String, @params : Array(Tree))
end
class TreeId < Tree
property id : String
def initialize(@id : String) end
def accept(v : Visitor)
v.visit(self)
@params.each &.accept(v)
v.finish(self)
end
end
class TreeOp < Tree
property op : TokenType
property left : Tree
property right : Tree
def initialize(@op : TokenType, @left : Tree, @right : Tree)
end
class TreeLit < Tree
property lit : Int64
def initialize(@lit : Int64) 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
class TreeCall < Tree
property name : String
property params : Array(Tree)
def accept(v : Visitor)
v.visit(self)
@children.each &.accept(v)
v.finish(self)
end
end
def initialize(@name : String, @params : Array(Tree)) end
def accept(v : Visitor)
v.visit(self)
@params.each &.accept(v)
v.finish(self)
end
class TreeFunction < Tree
property name : String
property params : Array(String)
property block : Tree
def initialize(@name : String, @params : Array(String), @block : Tree)
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)
@block.accept(v)
v.finish(self)
end
end
def accept(v : Visitor)
v.visit(self)
@left.accept(v)
@right.accept(v)
v.finish(self)
end
class TreeVar < Tree
property name : String
property expr : Tree
def initialize(@name : String, @expr : Tree)
end
class TreeBlock < Tree
def initialize(@children : Array(Tree)) end
def accept(v : Visitor)
v.visit(self)
@expr.accept(v)
v.finish(self)
end
end
def accept(v : Visitor)
v.visit(self)
@children.each &.accept(v)
v.finish(self)
end
class TreeAssign < Tree
property name : String
property expr : Tree
def initialize(@name : String, @expr : Tree)
end
class TreeFunction < Tree
property name : String
property params : Array(String)
property block : Tree
def accept(v : Visitor)
v.visit(self)
@expr.accept(v)
v.finish(self)
end
end
def initialize(@name : String, @params : Array(String), @block : Tree) end
def accept(v : Visitor)
v.visit(self)
@block.accept(v)
v.finish(self)
end
class TreeIf < Tree
property condition : Tree
property block : Tree
property otherwise : Tree?
def initialize(@condition : Tree, @block : Tree, @otherwise : Tree? = nil)
end
class TreeVar < Tree
property name : String
property expr : Tree
def accept(v : Visitor)
v.visit(self)
@condition.accept(v)
@block.accept(v)
@otherwise.try &.accept(v)
v.finish(self)
end
end
def initialize(@name : String, @expr : Tree) end
def accept(v : Visitor)
v.visit(self)
@expr.accept(v)
v.finish(self)
end
class TreeWhile < Tree
property condition : Tree
property block : Tree
def initialize(@condition : Tree, @block : Tree)
end
class TreeAssign < Tree
property name : String
property expr : Tree
def accept(v : Visitor)
v.visit(self)
@condition.accept(v)
@block.accept(v)
v.finish(self)
end
end
def initialize(@name : String, @expr : Tree) end
def accept(v : Visitor)
v.visit(self)
@expr.accept(v)
v.finish(self)
end
class TreeReturn < Tree
property rvalue : Tree
def initialize(@rvalue : Tree)
end
class TreeIf < Tree
property condition : Tree
property block : Tree
property otherwise : Tree?
def initialize(@condition : Tree, @block : Tree, @otherwise : Tree? = nil) end
def accept(v : Visitor)
v.visit(self)
@condition.accept(v)
@block.accept(v)
@otherwise.try &.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
def accept(v : Visitor)
v.visit(self)
@rvalue.accept(v)
v.finish(self)
end
end
end