From e21f070968abf0b6ca26db5eb01d723b4680ab18 Mon Sep 17 00:00:00 2001 From: alpha Date: Wed, 10 Aug 2022 00:01:35 +0000 Subject: [PATCH] 8.challenges.1 FossilOrigin-Name: 4dd1670a4466cf079d61e11677e4aa8dd9b9ec096700e2ae565a4073ec4efc12 --- ruby/bin/lox | 28 +++++------------------ ruby/lib/lox.rb | 44 +++++++++++++++++++++++++++++++------ ruby/lib/lox/interpreter.rb | 4 ++-- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/ruby/bin/lox b/ruby/bin/lox index 4cbfcbb..8e03bf6 100755 --- a/ruby/bin/lox +++ b/ruby/bin/lox @@ -4,33 +4,17 @@ $LOAD_PATH.unshift(File.expand_path("../lib", __dir__)) require "lox" -def run_prompt +def run_prompt(runner) loop do print "> " line = gets break if line.nil? || line.empty? - begin - run(line) - rescue Lox::ParseError => e - STDERR.puts e.message - rescue Lox::RuntimeError => e - STDERR.puts e.message - end + runner.run(line) end end -def run_file(io) - run(io.read) -rescue Lox::ParseError => e - STDERR.puts e.message - exit 65 -rescue Lox::RuntimeError => e - STDERR.puts e.message, "[line #{e.token.line}]" - exit 70 -end - -def run(src) - Lox::Runner.new.run(src) +def run_file(runner, io) + runner.run(io.read) end @@ -38,8 +22,8 @@ if __FILE__ == $0 puts "Usage: #$0 [script]" or exit 64 if ARGV.length > 1 if ARGV.empty? - run_prompt + run_prompt(Lox::PromptRunner.new) else - run_file(ARGF) + Lox::FileRunner.new.run(ARGF.read) end end diff --git a/ruby/lib/lox.rb b/ruby/lib/lox.rb index 3cb4e82..9a7ce98 100644 --- a/ruby/lib/lox.rb +++ b/ruby/lib/lox.rb @@ -10,18 +10,48 @@ require_relative "lox/token" module Lox class Runner + def initialize(scanner: Scanner.new, interpreter: Interpreter.new) + @scanner, @interpreter = scanner, interpreter + end + + def run(src) = interpret(parse(scan(src))) + + def scan(src) = @scanner.scan(src) + def parse(tokens) = Parser.new(tokens).parse! + def interpret(stmts) = @interpreter.interpret(stmts) + end + + class FileRunner < Runner + def run(src) + super + rescue Lox::ParseError => e + STDERR.puts e.message + exit 65 + rescue Lox::RuntimeError => e + STDERR.puts e.message, "[line #{e.token.line}]" + exit 70 + end + end + + class PromptRunner < Runner def initialize - @scanner = Scanner.new - @parser = Parser.new - @interpreter = Interpreter.new + super(interpreter: Interpreter.new(Environment.new)) end def run(src) - tokens = @scanner.scan(src) - expr = @parser.parse(tokens) - value = @interpreter.interpret(expr) + super + rescue Lox::ParseError => e + STDERR.puts e.message + rescue Lox::RuntimeError => e + STDERR.puts e.message + end - puts value + def parse(tokens) + stmts = Parser.new(tokens).parse! + if stmts.last.instance_of?(Stmt::Expr) + stmts << Stmt::Print.new(stmts.pop.expr) + end + stmts end end end diff --git a/ruby/lib/lox/interpreter.rb b/ruby/lib/lox/interpreter.rb index 3725811..0066043 100644 --- a/ruby/lib/lox/interpreter.rb +++ b/ruby/lib/lox/interpreter.rb @@ -3,8 +3,8 @@ require_relative "environment" module Lox class Interpreter - def initialize - @env = Environment.new + def initialize(env=Environment.new) + @env = env end # The book does printing and error catching here, but