lib/rus3/parser/scheme_parser.rb in rus3-0.1.0 vs lib/rus3/parser/scheme_parser.rb in rus3-0.1.1

- old
+ new

@@ -4,11 +4,11 @@ # A simple parser to read a s-expression for Scheme. class SchemeParser < Parser # Indicates the version of the parser class - PARSER_VERSION = "0.1.0" + PARSER_VERSION = "0.1.1" # Constructs the version string. def version vmsg = "(scheme-parser-version . #{PARSER_VERSION})" @@ -113,32 +113,43 @@ # (* x y)) ... s_exp # -> ["let", [["x", "2"], ["y", "3"]], # ["mul", "x", "y"]] ... i_exp # -> "lambda { |x, y| mul(x, y) }.call(2, 3)" ... r_exp # + # - vector (s_exp -> r_exp) + # - #(1 2 #(3 4) 5) + # -> "vector(1, 2, vector(3, 4), 5)" + # # - list (s_exp -> r_exp) # - (1 2 3 (4 5) (6 7 8) 9 0) # -> "[1, 2, 3, [4, 5], [6, 7, 8], 9, 0]" def parse(s_exp) parse_tokens(Lexer.new(s_exp)) end def parse_tokens(lexer) # :nodoc: r_exps = [] - loop { - token = lexer.next - if token.type == :lparen - i_exp = parse_compound(lexer) - r_exps << translate(i_exp) - else - r_exps << parse_primitive(token) - end - } + loop { r_exps << parse_s_exp(lexer) } r_exps.join("\n") end + def parse_s_exp(lexer) + r_exp = nil + token = lexer.next + case token.type + when :lparen + i_exp = parse_compound(lexer) + r_exp = translate(i_exp) + when :vec_lparen + r_exp = parse_vector(lexer) + else + r_exp = parse_primitive(token) + end + r_exp + end + def parse_primitive(token) r_exp = nil case token.type when *Lexer::KEYWORDS.values r_exp = translate_ident(token.literal) @@ -148,9 +159,33 @@ trans_method_name = "translate_#{token.type}".intern r_exp = self.send(trans_method_name, token.literal) else raise Rus3::SchemeSyntaxError, token.literal end + r_exp + end + + def parse_vector(lexer) + r_exp = "vector(" + Kernel.loop { + token = lexer.peek + case token.type + when :lparen + lexer.next + i_exp = parse_compound(lexer) + r_exp += translate(i_exp) + when :vec_lparen + lexer.next + r_exp += parse_vector(lexer) + when :rparen + lexer.next + r_exp = r_exp.sub(/,\s*\Z/, "") + ")" + break + else + r_exp += parse_s_exp(lexer) + end + r_exp += ", " + } r_exp end def parse_compound(lexer) i_exp = []