class Lisp::Parser
Public Class Methods
new()
click to toggle source
# File lib/rubylisp/parser.rb, line 5 def initialize end
Public Instance Methods
make_character(ch)
click to toggle source
# File lib/rubylisp/parser.rb, line 28 def make_character(ch) Lisp::Character.with_value(ch) end
make_float(str)
click to toggle source
# File lib/rubylisp/parser.rb, line 16 def make_float(str) Lisp::Number.with_value(str.to_f) end
make_hex_number(str)
click to toggle source
# File lib/rubylisp/parser.rb, line 12 def make_hex_number(str) Lisp::Number.with_value(["0x", str].join.to_i(0)) end
make_number(str)
click to toggle source
# File lib/rubylisp/parser.rb, line 8 def make_number(str) Lisp::Number.with_value(str.to_i) end
make_string(str)
click to toggle source
# File lib/rubylisp/parser.rb, line 20 def make_string(str) Lisp::String.with_value(str) end
make_symbol(str)
click to toggle source
# File lib/rubylisp/parser.rb, line 24 def make_symbol(str) Lisp::Symbol.named(str) end
parse(src)
click to toggle source
# File lib/rubylisp/parser.rb, line 248 def parse(src) tokenizer = Tokenizer.from_string(src) self.parse_sexpr(tokenizer) end
parse_and_eval(src, env=Lisp::EnvironmentFrame.global)
click to toggle source
# File lib/rubylisp/parser.rb, line 259 def parse_and_eval(src, env=Lisp::EnvironmentFrame.global) sexpr = self.parse(src) return sexpr.evaluate(env) end
parse_and_eval_all(src, env=Lisp::EnvironmentFrame.global)
click to toggle source
# File lib/rubylisp/parser.rb, line 264 def parse_and_eval_all(src, env=Lisp::EnvironmentFrame.global) tokenizer = Tokenizer.from_string(src) result = nil until tokenizer.eof? sexpr = self.parse_sexpr(tokenizer) result = sexpr.evaluate(env) end result end
parse_cons_cell(start_pos, tokens)
click to toggle source
# File lib/rubylisp/parser.rb, line 32 def parse_cons_cell(start_pos, tokens) pos, tok, lit = tokens.next_token if tok == :RPAREN tokens.consume_token return Lisp::ConsCell.cons().tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end end car = nil cdr = nil cells = [] while tok != :RPAREN if tok == :PERIOD tokens.consume_token cdr = self.parse_sexpr(tokens) return nil if tokens.next_token[0] == :EOF pos, tok, lit = tokens.next_token return Lisp::Debug.process_error("Expected ')' to follow a dotted tail on line #{tokens.line_number}", Lisp::EnvironmentFrame.global) if tok != :RPAREN tokens.consume_token return Lisp::ConsCell.array_to_list(cells, cdr).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end else car = self.parse_sexpr(tokens) return Lisp::Debug.process_error("Unexpected EOF (expected ')') on line #{tokens.line_number}", Lisp::EnvironmentFrame.global) if tokens.next_token[0] == :EOF cells << car end pos, tok, lit = tokens.next_token end tokens.consume_token Lisp::ConsCell.array_to_list(cells).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end end
parse_frame(start_pos, tokens, literal)
click to toggle source
# File lib/rubylisp/parser.rb, line 69 def parse_frame(start_pos, tokens, literal) m = {} pos, tok, lit = tokens.next_token if tok == :RBRACE tokens.consume_token if literal Lisp::Frame.new.tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end else Lisp::ConsCell.cons(Lisp::Symbol.named("make-frame"), nil).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end end else cells = [] while tok != :RBRACE item = self.parse_sexpr(tokens) return Lisp::Debug.process_error("Unexpected EOF (expected '}') on line #{tokens.line_number}", env) if tokens.next_token[0] == :EOF cells << item pos, tok, lit = tokens.next_token end tokens.consume_token keys_and_values = Lisp::ConsCell.array_to_list(cells) if literal Lisp::PrimFrame.make_frame_impl(keys_and_values, Lisp::EnvironmentFrame.global).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end else Lisp::ConsCell.cons(Lisp::Symbol.named("make-frame"), keys_and_values).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end end end end
parse_object_from_file(port, env=Lisp::EnvironmentFrame.global)
click to toggle source
# File lib/rubylisp/parser.rb, line 253 def parse_object_from_file(port, env=Lisp::EnvironmentFrame.global) tokenizer = Tokenizer.from_file(port) result = self.parse_sexpr(tokenizer) result.nil? ? Lisp::EofObject.instance : result end
parse_sexpr(tokens)
click to toggle source
# File lib/rubylisp/parser.rb, line 145 def parse_sexpr(tokens) while true pos, tok, lit = tokens.next_token # puts "token: <#{tok}, #{lit}>" return nil if tok == :EOF tokens.consume_token case tok when :COMMENT next when :NUMBER return make_number(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :FLOAT return make_float(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :HEXNUMBER return make_hex_number(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :STRING return make_string(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :CHARACTER return make_character(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :LPAREN return parse_cons_cell(pos, tokens) when :LBRACE return parse_frame(pos, tokens, false) when :QUOTE_LBRACE return parse_frame(pos, tokens, true) when :HASH_LPAREN return parse_vector(pos, tokens, false) when :QUOTE_HASH_LPAREN return parse_vector(pos, tokens, true) when :SYMBOL return make_symbol(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :FFI_NEW_SYMBOL return Lisp::FfiNew.new(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :FFI_SEND_SYMBOL return Lisp::FfiSend.new(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :FFI_STATIC_SYMBOL return Lisp::FfiStatic.new(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end when :FALSE if @parse_for_debugging return Lisp::Boolean.with_value(false).tap do |obj| obj.set_location(pos, 2) if @parse_for_debugging end else return Lisp::FALSE end when :TRUE if @parse_for_debugging return Lisp::Boolean.with_value(false).tap do |obj| obj.set_location(pos, 2) if @parse_for_debugging end else return Lisp::TRUE end when :QUOTE expr = parse_sexpr(tokens) return Lisp::ConsCell.array_to_list([Lisp::Symbol.named('quote'), expr]).tap do |obj| obj.set_location(pos, expr.src_length + 1) if @parse_for_debugging end when :BACKQUOTE expr = parse_sexpr(tokens) return Lisp::ConsCell.array_to_list([Lisp::Symbol.named('quasiquote'), expr]).tap do |obj| obj.set_location(pos, expr.src_length + 1) if @parse_for_debugging end when :COMMA expr = parse_sexpr(tokens) return Lisp::ConsCell.array_to_list([Lisp::Symbol.named('unquote'), expr]).tap do |obj| obj.set_location(pos, expr.src_length + 1) if @parse_for_debugging end when :COMMAAT expr = parse_sexpr(tokens) return Lisp::ConsCell.array_to_list([Lisp::Symbol.named('unquote-splicing'), expr]).tap do |obj| obj.set_location(pos, expr.src_length + 2) if @parse_for_debugging end when :WHITESPACE next when :ILLEGAL return Lisp::Debug.process_error("Illegal token: #{lit} on line #{tokens.line_number}", Lisp::EnvironmentFrame.global) else return make_symbol(lit).tap do |obj| obj.set_location(pos, lit.length) if @parse_for_debugging end end end end
parse_vector(start_pos, tokens, literal)
click to toggle source
# File lib/rubylisp/parser.rb, line 107 def parse_vector(start_pos, tokens, literal) v = [] pos, tok, lit = tokens.next_token if tok == :RPAREN tokens.consume_token if literal Lisp::Vector.new.tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end else Lisp::ConsCell.cons(Lis::Symbol.named("vector"), nil).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end end else cells = [] while tok != :RPAREN item = self.parse_sexpr(tokens) return Lisp::Debug.process_error("Unexpected EOF (expected ')') on line #{tokens.line_number}", env) if tokens.next_token[0] == :EOF cells << item pos, tok, lit = tokens.next_token end tokens.consume_token if literal Lisp::Vector.with_array(cells).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end else Lisp::ConsCell.cons(Lisp::Symbol.named("vector"), Lisp::ConsCell.array_to_list(cells)).tap do |obj| obj.set_location(start_pos, pos - start_pos + 1) if @parse_for_debugging end end end end
process_file(fname)
click to toggle source
# File lib/rubylisp/parser.rb, line 274 def process_file(fname) File.open(fname) do |f| parse_and_eval_all(f.read) end end