class Malady::Parser
Attributes
filename[R]
Public Class Methods
new(filename)
click to toggle source
# File lib/malady/parser.rb, line 5 def initialize(filename) @filename = filename @line = 0 end
Public Instance Methods
apply(fn, args)
click to toggle source
# File lib/malady/parser.rb, line 86 def apply(fn, args) if builtins.values.include? fn fn.new(@filename, @line, *args) else Malady::AST::FunctionCallNode.new(@filename, @line, fn, args) end end
builtins()
click to toggle source
# File lib/malady/parser.rb, line 94 def builtins { '+' => Malady::AST::AddNode, '-' => Malady::AST::MinusNode, '/' => Malady::AST::DivideNode, '*' => Malady::AST::MultiplyNode, '<' => Malady::AST::LessThanNode, } end
on_error(t, val, vstack)
click to toggle source
# File lib/malady/parser.rb, line 109 def on_error(t, val, vstack) raise ParseError, sprintf("\nparse error on value %s (%s) #{@filename}:#{@line}", val.inspect, token_to_str(t) || '?') end
parse(sexp)
click to toggle source
# File lib/malady/parser.rb, line 16 def parse(sexp) type, *rest = sexp if type == :list symbol = rest.first case symbol[1] when 'def!' parse_def(sexp) when 'let*' parse_let(sexp) when 'if' parse_if(sexp) when 'fn*' parse_fn(sexp) else fn, *args = parse_sexp(sexp) apply(fn, args) end else parse_sexp(sexp) end end
parse_def(sexp)
click to toggle source
# File lib/malady/parser.rb, line 58 def parse_def(sexp) # [:list, [:symbol, 'def!'], [:symbol, 'blah'], sexp] name = sexp[2][1] value = sexp[3] Malady::AST::AssignNode.new(@filename, @line, name, parse(value)) end
parse_fn(sexp)
click to toggle source
# File lib/malady/parser.rb, line 79 def parse_fn(sexp) # [:list, [:symbol, 'fn*'], [:list, [:symbol, 'x']], body] _, _, (_, *arguments), body = sexp arguments = arguments.map(&:last) Malady::AST::FnNode.new(@filename, @line, arguments, parse(body)) end
parse_if(sexp)
click to toggle source
# File lib/malady/parser.rb, line 73 def parse_if(sexp) # [:list, [:symbol, 'if'], condition, then_branch, else_branch] _, _, condition, then_branch, else_branch = sexp Malady::AST::IfNode.new(@filename, @line, parse(condition), parse(then_branch), parse(else_branch)) end
parse_let(sexp)
click to toggle source
# File lib/malady/parser.rb, line 65 def parse_let(sexp) # [:list, [:symbol, 'let'], [:list, [:symbol, 'c'], sexp], sexp] bindings = sexp[2][1..-1].each_slice(2).to_a body = sexp[3] parsed_bindings = bindings.map { |s, val| [s[1], parse(val)] } Malady::AST::LetNode.new(@filename, @line, parsed_bindings, parse(body)) end
parse_sexp(sexp)
click to toggle source
# File lib/malady/parser.rb, line 38 def parse_sexp(sexp) type, *rest = sexp case type when :boolean boolean = sexp.last if boolean == :true Malady::AST::TrueBooleanNode.new(@filename, @line) else Malady::AST::FalseBooleanNode.new(@filename, @line) end when :symbol name = sexp.last builtins.fetch(name, Malady::AST::SymbolNode.new(@filename, @line, name)) when :integer Malady::AST::IntegerNode.new @filename, @line, sexp[1] when :list rest.map { |sexp| parse(sexp) } end end
parse_string(string)
click to toggle source
# File lib/malady/parser.rb, line 10 def parse_string(string) sexp = Reader.read_str(string) program_body = [parse(sexp)] Malady::AST::Program.new @filename, @line, program_body end
pre_exe()
click to toggle source
the following methods are needed to conform with RBX's parser interface
# File lib/malady/parser.rb, line 105 def pre_exe [] end