diff --git a/ruby/Gemfile b/ruby/Gemfile new file mode 100644 index 0000000..88bd7be --- /dev/null +++ b/ruby/Gemfile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } + +gem "minitest" +gem "pry" diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock new file mode 100644 index 0000000..911cc11 --- /dev/null +++ b/ruby/Gemfile.lock @@ -0,0 +1,19 @@ +GEM + remote: https://rubygems.org/ + specs: + coderay (1.1.3) + method_source (1.0.0) + minitest (5.16.2) + pry (0.14.1) + coderay (~> 1.1) + method_source (~> 1.0) + +PLATFORMS + arm64-darwin-21 + +DEPENDENCIES + minitest + pry + +BUNDLED WITH + 2.3.18 diff --git a/ruby/Rakefile b/ruby/Rakefile new file mode 100644 index 0000000..bfd5f99 --- /dev/null +++ b/ruby/Rakefile @@ -0,0 +1,6 @@ +require "minitest/test_task" + +Minitest::TestTask.create do |t| + t.test_globs = "./test_*.rb" +end +task default: :test diff --git a/ruby/lox.rb b/ruby/lox.rb new file mode 100755 index 0000000..af9d26d --- /dev/null +++ b/ruby/lox.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby -w + +module Lox + class << self + @had_error = false + end + + def self.run_prompt + loop do + print "> " + line = gets + break if line.empty? + run(line) + @had_error = false + end + end + + def self.run_file(io) + run(io.read) + + exit 65 if @had_error + end + + def self.run(src) + scanner = Scanner.new(src) + tokens = scanner.scan() + + tokens.each do |token| + puts token + end + end + + def self.error(line, msg) + report(line, "", msg) + end + + def self.report(line, where, message) + puts "[line #{line}] Error#{where}: #{message}" + @had_error = true; + end +end + +if __FILE__ == $0 + puts "Usage: #$0 [script]" or exit 64 if ARGV.length > 1 + + if ARGV.empty? + Lox.run_prompt + else + Lox.run_file(ARGF) + end +end diff --git a/ruby/test_lox.rb b/ruby/test_lox.rb new file mode 100644 index 0000000..1424231 --- /dev/null +++ b/ruby/test_lox.rb @@ -0,0 +1,14 @@ +require "minitest/autorun" + +require "lox" + +require "open3" +require "pry" + +class TestLox < Minitest::Test + def test_error_on_more_than_one_arg + o, s = Open3.capture2("./lox.rb foo bar") + assert_equal 64, s.exitstatus + assert_equal "Usage: ./lox.rb [script]\n", o + end +end