Class: Malady::Parser
- Inherits:
-
Object
- Object
- Malady::Parser
- Defined in:
- lib/malady/parser.rb
Instance Attribute Summary collapse
-
#filename ⇒ Object
readonly
Returns the value of attribute filename.
Instance Method Summary collapse
- #apply(fn, args) ⇒ Object
- #builtins ⇒ Object
-
#initialize(filename) ⇒ Parser
constructor
A new instance of Parser.
- #on_error(t, val, vstack) ⇒ Object
- #parse(sexp) ⇒ Object
- #parse_def(sexp) ⇒ Object
- #parse_fn(sexp) ⇒ Object
- #parse_if(sexp) ⇒ Object
- #parse_let(sexp) ⇒ Object
- #parse_sexp(sexp) ⇒ Object
- #parse_string(string) ⇒ Object
-
#pre_exe ⇒ Object
the following methods are needed to conform with RBX’s parser interface.
Constructor Details
#initialize(filename) ⇒ Parser
Returns a new instance of Parser.
5 6 7 8 |
# File 'lib/malady/parser.rb', line 5 def initialize(filename) @filename = filename @line = 0 end |
Instance Attribute Details
#filename ⇒ Object (readonly)
Returns the value of attribute filename.
3 4 5 |
# File 'lib/malady/parser.rb', line 3 def filename @filename end |
Instance Method Details
#apply(fn, args) ⇒ Object
86 87 88 89 90 91 92 |
# 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 ⇒ Object
94 95 96 97 98 99 100 101 102 |
# 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) ⇒ Object
109 110 111 112 |
# 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) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# 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) ⇒ Object
58 59 60 61 62 63 |
# 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) ⇒ Object
79 80 81 82 83 84 |
# 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) ⇒ Object
73 74 75 76 77 |
# 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) ⇒ Object
65 66 67 68 69 70 71 |
# 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) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# 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) ⇒ Object
10 11 12 13 14 |
# 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 ⇒ Object
the following methods are needed to conform with RBX’s parser interface
105 106 107 |
# File 'lib/malady/parser.rb', line 105 def pre_exe [] end |