Run the format tool.
This commit is contained in:
parent
fa00bda8ab
commit
df2a00fd66
14
src/chalk.cr
14
src/chalk.cr
|
@ -1,12 +1,12 @@
|
||||||
require "./chalk/*"
|
require "./chalk/*"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
lexer = Lexer.new
|
lexer = Lexer.new
|
||||||
parser = Parser.new
|
parser = Parser.new
|
||||||
|
|
||||||
tokens = lexer.lex(File.read("test.txt"))
|
tokens = lexer.lex(File.read("test.txt"))
|
||||||
trees = parser.parse?(tokens)
|
trees = parser.parse?(tokens)
|
||||||
trees.try do |trees|
|
trees.try do |trees|
|
||||||
trees.each &.accept(PrintVisitor.new)
|
trees.each &.accept(PrintVisitor.new)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,37 +2,37 @@ require "./lexer.cr"
|
||||||
require "./parsers.cr"
|
require "./parsers.cr"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
module Builder
|
module Builder
|
||||||
def type(type): BasicParser(Token)
|
def type(type) : BasicParser(Token)
|
||||||
return TypeParser.new(type).as(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
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
|
@ -1,82 +1,82 @@
|
||||||
require "lex"
|
require "lex"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
enum TokenType
|
enum TokenType
|
||||||
Any,
|
Any,
|
||||||
Str,
|
Str,
|
||||||
Id,
|
Id,
|
||||||
LitDec,
|
LitDec,
|
||||||
LitBin,
|
LitBin,
|
||||||
LitHex,
|
LitHex,
|
||||||
OpAdd
|
OpAdd
|
||||||
OpSub
|
OpSub
|
||||||
OpMul
|
OpMul
|
||||||
OpDiv
|
OpDiv
|
||||||
OpOr
|
OpOr
|
||||||
OpAnd
|
OpAnd
|
||||||
OpXor
|
OpXor
|
||||||
KwSprite
|
KwSprite
|
||||||
KwInline
|
KwInline
|
||||||
KwFun
|
KwFun
|
||||||
KwU0
|
KwU0
|
||||||
KwU8
|
KwU8
|
||||||
KwU12
|
KwU12
|
||||||
KwVar
|
KwVar
|
||||||
KwIf
|
KwIf
|
||||||
KwElse
|
KwElse
|
||||||
KwWhile
|
KwWhile
|
||||||
KwReturn
|
KwReturn
|
||||||
|
end
|
||||||
|
|
||||||
|
class Token
|
||||||
|
def initialize(@string : String, @type : TokenType)
|
||||||
end
|
end
|
||||||
|
|
||||||
class Token
|
getter string : String
|
||||||
def initialize(@string : String, @type : TokenType)
|
getter type : TokenType
|
||||||
end
|
end
|
||||||
|
|
||||||
getter string : String
|
class Lexer
|
||||||
getter type : TokenType
|
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
|
end
|
||||||
|
|
||||||
class Lexer
|
def lex(string)
|
||||||
def initialize
|
return @lexer.lex(string)
|
||||||
@lexer = Lex::Lexer.new
|
.select { |t| !t[0][0].whitespace? }
|
||||||
@lexer.add_pattern(".", TokenType::Any.value)
|
.map do |tuple|
|
||||||
@lexer.add_pattern("\"(\\\\\"|[^\"])*\"",
|
string, id = tuple
|
||||||
TokenType::Str.value)
|
Token.new(string, TokenType.new(id))
|
||||||
@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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,173 +1,173 @@
|
||||||
require "./builder.cr"
|
require "./builder.cr"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
class Parser
|
class Parser
|
||||||
include Builder
|
include Builder
|
||||||
|
|
||||||
private def create_type
|
private def create_type
|
||||||
either(type(TokenType::KwU0), type(TokenType::KwU8), type(TokenType::KwU12))
|
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
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
|
@ -1,151 +1,149 @@
|
||||||
require "./builder.cr"
|
require "./builder.cr"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
|
abstract class BasicParser(T)
|
||||||
|
abstract def parse?(tokens : Array(Token),
|
||||||
|
index : Int64) : Tuple(T, Int64)?
|
||||||
|
|
||||||
abstract class BasicParser(T)
|
def parse(tokens : Array(Token),
|
||||||
abstract def parse?(tokens : Array(Token),
|
index : Int64) : Tuple(T, Int64)
|
||||||
index : Int64): Tuple(T, Int64)?
|
return parse?(tokens, index).not_nil!
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TypeParser < BasicParser(Token)
|
def transform(&transform : T -> R) forall R
|
||||||
def initialize(@type : TokenType)
|
return TransformParser.new(self, &transform).as(BasicParser(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
|
end
|
||||||
|
|
||||||
class CharParser < BasicParser(Token)
|
def then(other : BasicParser(R)) : BasicParser(Array(T | R)) forall R
|
||||||
def initialize(@char : Char)
|
return NextParser.new(self, other).as(BasicParser(Array(T | R)))
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class TypeParser < BasicParser(Token)
|
||||||
return nil unless index < tokens.size
|
def initialize(@type : TokenType)
|
||||||
return nil unless (tokens[index].type == TokenType::Any) &&
|
|
||||||
tokens[index].string[0] == @char
|
|
||||||
return { tokens[index], index + 1}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TransformParser(T, R) < BasicParser(R)
|
def parse?(tokens, index)
|
||||||
def initialize(@parser : BasicParser(T), &@block : T -> R)
|
return nil unless index < tokens.size
|
||||||
end
|
return nil unless tokens[index].type == @type
|
||||||
|
return {tokens[index], index + 1}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class CharParser < BasicParser(Token)
|
||||||
if parsed = @parser.parse?(tokens, index)
|
def initialize(@char : Char)
|
||||||
return { @block.call(parsed[0]), parsed[1] }
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class OptionalParser(T) < BasicParser(T?)
|
def parse?(tokens, index)
|
||||||
def initialize(@parser : BasicParser(T))
|
return nil unless index < tokens.size
|
||||||
end
|
return nil unless (tokens[index].type == TokenType::Any) &&
|
||||||
|
tokens[index].string[0] == @char
|
||||||
|
return {tokens[index], index + 1}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class TransformParser(T, R) < BasicParser(R)
|
||||||
if parsed = @parser.parse?(tokens, index)
|
def initialize(@parser : BasicParser(T), &@block : T -> R)
|
||||||
return { parsed[0], parsed[1] }
|
|
||||||
end
|
|
||||||
return { nil, index }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class EitherParser(T) < BasicParser(T)
|
def parse?(tokens, index)
|
||||||
def initialize(@parsers : Array(BasicParser(T)))
|
if parsed = @parser.parse?(tokens, index)
|
||||||
end
|
return {@block.call(parsed[0]), parsed[1]}
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class OptionalParser(T) < BasicParser(T?)
|
||||||
@parsers.each do |parser|
|
def initialize(@parser : BasicParser(T))
|
||||||
if parsed = parser.parse?(tokens, index)
|
|
||||||
return parsed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ManyParser(T) < BasicParser(Array(T))
|
def parse?(tokens, index)
|
||||||
def initialize(@parser : BasicParser(T))
|
if parsed = @parser.parse?(tokens, index)
|
||||||
end
|
return {parsed[0], parsed[1]}
|
||||||
|
end
|
||||||
|
return {nil, index}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class EitherParser(T) < BasicParser(T)
|
||||||
many = [] of T
|
def initialize(@parsers : Array(BasicParser(T)))
|
||||||
while parsed = @parser.parse?(tokens, index)
|
|
||||||
item, index = parsed
|
|
||||||
many << item
|
|
||||||
end
|
|
||||||
return { many, index }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class DelimitedParser(T, R) < BasicParser(Array(T))
|
def parse?(tokens, index)
|
||||||
def initialize(@parser : BasicParser(T), @delimiter : BasicParser(R))
|
@parsers.each do |parser|
|
||||||
|
if parsed = parser.parse?(tokens, index)
|
||||||
|
return parsed
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class ManyParser(T) < BasicParser(Array(T))
|
||||||
array = [] of T
|
def initialize(@parser : BasicParser(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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class NextParser(T, R) < BasicParser(Array(T | R))
|
def parse?(tokens, index)
|
||||||
def initialize(@first : BasicParser(T), @second : BasicParser(R))
|
many = [] of T
|
||||||
end
|
while parsed = @parser.parse?(tokens, index)
|
||||||
|
item, index = parsed
|
||||||
|
many << item
|
||||||
|
end
|
||||||
|
return {many, index}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse?(tokens, index)
|
class DelimitedParser(T, R) < BasicParser(Array(T))
|
||||||
first = @first.parse?(tokens, index)
|
def initialize(@parser : BasicParser(T), @delimiter : BasicParser(R))
|
||||||
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
|
end
|
||||||
|
|
||||||
class PlaceholderParser(T) < BasicParser(T)
|
def parse?(tokens, index)
|
||||||
property parser : BasicParser(T)?
|
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
|
return {array, index}
|
||||||
@parser = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse?(tokens, index)
|
|
||||||
@parser.try &.parse?(tokens, index)
|
|
||||||
end
|
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -1,53 +1,53 @@
|
||||||
require "./tree.cr"
|
require "./tree.cr"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
class PrintVisitor < Visitor
|
class PrintVisitor < Visitor
|
||||||
def initialize
|
def initialize
|
||||||
@indent = 0
|
@indent = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_indent
|
def print_indent
|
||||||
@indent.times do
|
@indent.times do
|
||||||
STDOUT << " "
|
STDOUT << " "
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit(id : TreeId)
|
def visit(id : TreeId)
|
||||||
print_indent
|
print_indent
|
||||||
puts id.id
|
puts id.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit(lit : TreeLit)
|
def visit(lit : TreeLit)
|
||||||
print_indent
|
print_indent
|
||||||
puts lit.lit
|
puts lit.lit
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit(op : TreeOp)
|
def visit(op : TreeOp)
|
||||||
print_indent
|
print_indent
|
||||||
STDOUT << "[op] "
|
STDOUT << "[op] "
|
||||||
puts op.op
|
puts op.op
|
||||||
@indent += 1
|
@indent += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def finish(op : TreeOp)
|
def finish(op : TreeOp)
|
||||||
@indent -= 1
|
@indent -= 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit(function : TreeFunction)
|
def visit(function : TreeFunction)
|
||||||
print_indent
|
print_indent
|
||||||
STDOUT << "[function] " << function.name << "( "
|
STDOUT << "[function] " << function.name << "( "
|
||||||
function.params.each do |param|
|
function.params.each do |param|
|
||||||
STDOUT << param << " "
|
STDOUT << param << " "
|
||||||
end
|
end
|
||||||
puts ")"
|
puts ")"
|
||||||
@indent += 1
|
@indent += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def finish(function : TreeFunction)
|
def finish(function : TreeFunction)
|
||||||
@indent -= 1
|
@indent -= 1
|
||||||
end
|
end
|
||||||
|
|
||||||
macro forward(text, type)
|
macro forward(text, type)
|
||||||
def visit(tree : {{type}})
|
def visit(tree : {{type}})
|
||||||
print_indent
|
print_indent
|
||||||
puts {{text}}
|
puts {{text}}
|
||||||
|
@ -59,12 +59,12 @@ module Chalk
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
forward("[call]", TreeCall)
|
forward("[call]", TreeCall)
|
||||||
forward("[block]", TreeBlock)
|
forward("[block]", TreeBlock)
|
||||||
forward("[var]", TreeVar)
|
forward("[var]", TreeVar)
|
||||||
forward("[assign]", TreeAssign)
|
forward("[assign]", TreeAssign)
|
||||||
forward("[if]", TreeIf)
|
forward("[if]", TreeIf)
|
||||||
forward("[while]", TreeWhile)
|
forward("[while]", TreeWhile)
|
||||||
forward("[return]", TreeReturn)
|
forward("[return]", TreeReturn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,138 +1,159 @@
|
||||||
module Chalk
|
module Chalk
|
||||||
class Visitor
|
class Visitor
|
||||||
def visit(tree : Tree)
|
def visit(tree : Tree)
|
||||||
end
|
|
||||||
|
|
||||||
def finish(tree : Tree)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Tree
|
def finish(tree : Tree)
|
||||||
def accept(v : Visitor)
|
end
|
||||||
v.visit(self)
|
end
|
||||||
v.finish(self)
|
|
||||||
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
|
end
|
||||||
|
|
||||||
class TreeId < Tree
|
def accept(v : Visitor)
|
||||||
property id : String
|
v.visit(self)
|
||||||
def initialize(@id : String) end
|
@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
|
end
|
||||||
|
|
||||||
class TreeLit < Tree
|
def accept(v : Visitor)
|
||||||
property lit : Int64
|
v.visit(self)
|
||||||
def initialize(@lit : Int64) end
|
@left.accept(v)
|
||||||
|
@right.accept(v)
|
||||||
|
v.finish(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class TreeBlock < Tree
|
||||||
|
def initialize(@children : Array(Tree))
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeCall < Tree
|
def accept(v : Visitor)
|
||||||
property name : String
|
v.visit(self)
|
||||||
property params : Array(Tree)
|
@children.each &.accept(v)
|
||||||
|
v.finish(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(@name : String, @params : Array(Tree)) end
|
class TreeFunction < Tree
|
||||||
def accept(v : Visitor)
|
property name : String
|
||||||
v.visit(self)
|
property params : Array(String)
|
||||||
@params.each &.accept(v)
|
property block : Tree
|
||||||
v.finish(self)
|
|
||||||
end
|
def initialize(@name : String, @params : Array(String), @block : Tree)
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeOp < Tree
|
def accept(v : Visitor)
|
||||||
property op : TokenType
|
v.visit(self)
|
||||||
property left : Tree
|
@block.accept(v)
|
||||||
property right : Tree
|
v.finish(self)
|
||||||
def initialize(@op : TokenType, @left : Tree, @right : Tree) end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def accept(v : Visitor)
|
class TreeVar < Tree
|
||||||
v.visit(self)
|
property name : String
|
||||||
@left.accept(v)
|
property expr : Tree
|
||||||
@right.accept(v)
|
|
||||||
v.finish(self)
|
def initialize(@name : String, @expr : Tree)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeBlock < Tree
|
def accept(v : Visitor)
|
||||||
def initialize(@children : Array(Tree)) end
|
v.visit(self)
|
||||||
|
@expr.accept(v)
|
||||||
|
v.finish(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def accept(v : Visitor)
|
class TreeAssign < Tree
|
||||||
v.visit(self)
|
property name : String
|
||||||
@children.each &.accept(v)
|
property expr : Tree
|
||||||
v.finish(self)
|
|
||||||
end
|
def initialize(@name : String, @expr : Tree)
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeFunction < Tree
|
def accept(v : Visitor)
|
||||||
property name : String
|
v.visit(self)
|
||||||
property params : Array(String)
|
@expr.accept(v)
|
||||||
property block : Tree
|
v.finish(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(@name : String, @params : Array(String), @block : Tree) end
|
class TreeIf < Tree
|
||||||
def accept(v : Visitor)
|
property condition : Tree
|
||||||
v.visit(self)
|
property block : Tree
|
||||||
@block.accept(v)
|
property otherwise : Tree?
|
||||||
v.finish(self)
|
|
||||||
end
|
def initialize(@condition : Tree, @block : Tree, @otherwise : Tree? = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeVar < Tree
|
def accept(v : Visitor)
|
||||||
property name : String
|
v.visit(self)
|
||||||
property expr : Tree
|
@condition.accept(v)
|
||||||
|
@block.accept(v)
|
||||||
|
@otherwise.try &.accept(v)
|
||||||
|
v.finish(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(@name : String, @expr : Tree) end
|
class TreeWhile < Tree
|
||||||
def accept(v : Visitor)
|
property condition : Tree
|
||||||
v.visit(self)
|
property block : Tree
|
||||||
@expr.accept(v)
|
|
||||||
v.finish(self)
|
def initialize(@condition : Tree, @block : Tree)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeAssign < Tree
|
def accept(v : Visitor)
|
||||||
property name : String
|
v.visit(self)
|
||||||
property expr : Tree
|
@condition.accept(v)
|
||||||
|
@block.accept(v)
|
||||||
|
v.finish(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(@name : String, @expr : Tree) end
|
class TreeReturn < Tree
|
||||||
def accept(v : Visitor)
|
property rvalue : Tree
|
||||||
v.visit(self)
|
|
||||||
@expr.accept(v)
|
def initialize(@rvalue : Tree)
|
||||||
v.finish(self)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeIf < Tree
|
def accept(v : Visitor)
|
||||||
property condition : Tree
|
v.visit(self)
|
||||||
property block : Tree
|
@rvalue.accept(v)
|
||||||
property otherwise : Tree?
|
v.finish(self)
|
||||||
|
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user