class RbScheme::Parser
Constants
- EOF
Public Class Methods
new(input)
click to toggle source
# File lib/rb-scheme/parser.rb, line 15 def initialize(input) @input = input end
read_expr(input)
click to toggle source
# File lib/rb-scheme/parser.rb, line 11 def self.read_expr(input) new(input).read_expr end
Public Instance Methods
read_expr()
click to toggle source
# File lib/rb-scheme/parser.rb, line 19 def read_expr loop do c = getc case c when /\s/ next when EOF return nil when ';' skip_line next when '(' return read_list when ')' return LCloseParen.instance when '.' return LDot.instance when '\'' return read_quote when /\d/ return LInt.new(read_number(c.to_i)) when negative_number_pred return LInt.new(-read_number(c.to_i)) when '#' return read_hash when symbol_rp return read_symbol(c) else raise "Unexpected character - #{c}" end end end
Private Instance Methods
negative_number_pred()
click to toggle source
# File lib/rb-scheme/parser.rb, line 137 def negative_number_pred Proc.new {|c| '-' == c && /\d/ === peek} end
peek()
click to toggle source
# File lib/rb-scheme/parser.rb, line 54 def peek c = getc @input.ungetc(c) c end
read_hash()
click to toggle source
# File lib/rb-scheme/parser.rb, line 117 def read_hash c = getc case c when 't' LTrue.instance when 'f' LFalse.instance else raise "Unexpected hash literal #{c}" end end
read_list()
click to toggle source
# File lib/rb-scheme/parser.rb, line 78 def read_list acc = list loop do obj = read_expr raise "read_list: Unclosed parenthesis" if obj.nil? case obj when LCloseParen return reverse_list(acc) when LDot last = read_expr close = read_expr if close.nil? || !(LCloseParen === close) raise "read_list: Unclosed parenthesis" end if acc.null? raise "read_list: dotted list must have car" end return acc.reduce(last) { |res, e| cons(e, res) } else acc = cons(obj, acc) end end end
read_number(value)
click to toggle source
# File lib/rb-scheme/parser.rb, line 109 def read_number(value) result = value while /\d/ === peek result = result * 10 + getc.to_i end result end
read_quote()
click to toggle source
# File lib/rb-scheme/parser.rb, line 104 def read_quote sym = intern("quote") list(sym, read_expr) end
read_symbol(first_char)
click to toggle source
# File lib/rb-scheme/parser.rb, line 129 def read_symbol(first_char) result = first_char while symbol_rp === peek result += getc end intern(result) end
reverse_list(lst)
click to toggle source
# File lib/rb-scheme/parser.rb, line 60 def reverse_list(lst) return lst if lst.null? lst.reduce(list) { |res, e| cons(e, res) } end
skip_line()
click to toggle source
# File lib/rb-scheme/parser.rb, line 65 def skip_line loop do c = getc case c when EOF, "\n" return when "\r" getc if "\n" == peek return end end end
symbol_rp()
click to toggle source
# File lib/rb-scheme/parser.rb, line 141 def symbol_rp allowed = '~!@$%^&*-_=+:/?<>' Regexp.new("[A-Za-z0-9#{Regexp.escape(allowed)}]") end