Skip to content

Commit

Permalink
Merge pull request #56 from yui-knk/refactor_command
Browse files Browse the repository at this point in the history
Refactor Command class
  • Loading branch information
yui-knk authored Jul 30, 2023
2 parents 60db6ed + 395fb17 commit 44b8cb4
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 81 deletions.
2 changes: 1 addition & 1 deletion exe/lrama
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
$LOAD_PATH << File.join(__dir__, "../lib")
require "lrama"

Lrama::Command.new.run(ARGV.dup)
Lrama::Command.new(ARGV.dup).run
162 changes: 90 additions & 72 deletions lib/lrama/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,95 +2,57 @@

module Lrama
class Command
def run(argv)
opt = OptionParser.new

# opt.on('-h') {|v| p v }
opt.on('-V', '--version') {|v| puts Lrama::VERSION ; exit 0 }

# Tuning the Parser
skeleton = "bison/yacc.c"

opt.on('-S', '--skeleton=FILE') {|v| skeleton = v }
opt.on('-t') { } # Do nothing

# Output Files:
header = false
header_file = nil
report = []
report_file = nil
outfile = "y.tab.c"

opt.on('-h', '--header=[FILE]') {|v| header = true; header_file = v }
opt.on('-d') { header = true }
opt.on('-r', '--report=THINGS') {|v| report = v.split(',') }
opt.on('--report-file=FILE') {|v| report_file = v }
opt.on('-v') { } # Do nothing
opt.on('-o', '--output=FILE') {|v| outfile = v }

# Hidden
trace = []
opt.on('--trace=THINGS') {|v| trace = v.split(',') }

# Error Recovery
error_recovery = false
opt.on('-e') {|v| error_recovery = true }

opt.parse!(argv)

trace_opts = validate_trace(trace)
report_opts = validate_report(report)

grammar_file = argv.shift

if !report.empty? && report_file.nil? && grammar_file
report_file = File.dirname(grammar_file) + "/" + File.basename(grammar_file, ".*") + ".output"
end
def initialize(argv)
@argv = argv

@version = nil
@skeleton = "bison/yacc.c"
@header = false
@header_file = nil
@report = []
@report_file = nil
@outfile = "y.tab.c"
@trace = []
@error_recovery = false
@grammar_file = nil
@report_file = nil
@trace_opts = nil
@report_opts = nil
end

if !header_file && header
case
when outfile
header_file = File.dirname(outfile) + "/" + File.basename(outfile, ".*") + ".h"
when grammar_file
header_file = File.dirname(grammar_file) + "/" + File.basename(grammar_file, ".*") + ".h"
end
end
def run
parse_option

if !grammar_file
abort "File should be specified\n"
if @version
puts Lrama::VERSION
exit 0
end

Report::Duration.enable if trace_opts[:time]
Report::Duration.enable if @trace_opts[:time]

warning = Lrama::Warning.new
if grammar_file == '-'
grammar_file = argv.shift or abort "File name for STDIN should be specified\n"
y = STDIN.read
else
y = File.read(grammar_file)
end
grammar = Lrama::Parser.new(y).parse
states = Lrama::States.new(grammar, warning, trace_state: (trace_opts[:automaton] || trace_opts[:closure]))
grammar = Lrama::Parser.new(@y.read).parse
states = Lrama::States.new(grammar, warning, trace_state: (@trace_opts[:automaton] || @trace_opts[:closure]))
states.compute
context = Lrama::Context.new(states)

if report_file
if @report_file
reporter = Lrama::StatesReporter.new(states)
File.open(report_file, "w+") do |f|
reporter.report(f, **report_opts)
File.open(@report_file, "w+") do |f|
reporter.report(f, **@report_opts)
end
end

File.open(outfile, "w+") do |f|
File.open(@outfile, "w+") do |f|
Lrama::Output.new(
out: f,
output_file_path: outfile,
template_name: skeleton,
grammar_file_path: grammar_file,
header_file_path: header_file,
output_file_path: @outfile,
template_name: @skeleton,
grammar_file_path: @grammar_file,
header_file_path: @header_file,
context: context,
grammar: grammar,
error_recovery: error_recovery,
error_recovery: @error_recovery,
).render
end

Expand Down Expand Up @@ -145,5 +107,61 @@ def validate_trace(trace)

return h
end

def parse_option
opt = OptionParser.new

# opt.on('-h') {|v| p v }
opt.on('-V', '--version') {|v| @version = true }

# Tuning the Parser
opt.on('-S', '--skeleton=FILE') {|v| @skeleton = v }
opt.on('-t') { } # Do nothing

# Output Files:
opt.on('-h', '--header=[FILE]') {|v| @header = true; @header_file = v }
opt.on('-d') { @header = true }
opt.on('-r', '--report=THINGS') {|v| @report = v.split(',') }
opt.on('--report-file=FILE') {|v| @report_file = v }
opt.on('-v') { } # Do nothing
opt.on('-o', '--output=FILE') {|v| @outfile = v }

# Hidden
opt.on('--trace=THINGS') {|v| @trace = v.split(',') }

# Error Recovery
opt.on('-e') {|v| @error_recovery = true }

opt.parse!(@argv)

@trace_opts = validate_trace(@trace)
@report_opts = validate_report(@report)

@grammar_file = @argv.shift

if !@grammar_file
abort "File should be specified\n"
end

if @grammar_file == '-'
@grammar_file = @argv.shift or abort "File name for STDIN should be specified\n"
@y = STDIN
else
@y = File.open(@grammar_file, 'r')
end

if !@report.empty? && @report_file.nil? && @grammar_file
@report_file = File.dirname(@grammar_file) + "/" + File.basename(@grammar_file, ".*") + ".output"
end

if !@header_file && @header
case
when @outfile
@header_file = File.dirname(@outfile) + "/" + File.basename(@outfile, ".*") + ".h"
when @grammar_file
@header_file = File.dirname(@grammar_file) + "/" + File.basename(@grammar_file, ".*") + ".h"
end
end
end
end
end
106 changes: 99 additions & 7 deletions spec/lrama/command_spec.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
RSpec.describe Lrama::Command do
describe "#run" do
let(:command) { Lrama::Command.new }

describe "a grammar file is specified " do
it "ends successfully" do
expect(command.run([fixture_path("command/basic.y")])).to be_nil
command = Lrama::Command.new([fixture_path("command/basic.y")])
expect(command.run).to be_nil
end
end

describe "STDIN mode and a grammar file is specified" do
it "ends successfully" do
File.open(fixture_path("command/basic.y")) do |f|
allow(STDIN).to receive(:read).and_return(f)
expect(command.run(["-", "test.y"])).to be_nil
command = Lrama::Command.new(["-", "test.y"])
expect(command.run).to be_nil
end
end
end

describe "invalid argv" do
describe "a grammar file isn't specified" do
it "returns stderr" do
expect{ command.run([]) }.to raise_error(SystemExit) do |e|
command = Lrama::Command.new([])
expect{ command.run }.to raise_error(SystemExit) do |e|
expect(e.message).to eq("File should be specified\n")
end
end
end

describe "STDIN mode, but a grammar file isn't specified" do
it "returns stderr" do
expect{ command.run(["-"]) }.to raise_error(SystemExit) do |e|
command = Lrama::Command.new(["-"])
expect{ command.run }.to raise_error(SystemExit) do |e|
expect(e.message).to eq("File name for STDIN should be specified\n")
end
end
Expand All @@ -37,7 +39,7 @@
end

describe "#validate_report" do
let(:command) { Lrama::Command.new }
let(:command) { Lrama::Command.new([]) }

describe "valid options are passed" do
it "returns option hash" do
Expand All @@ -62,4 +64,94 @@
end
end
end

describe "@grammar_file" do
context "file is specified" do
it "@grammar_file is file name" do
command = Lrama::Command.new([fixture_path("command/basic.y")])
command.send(:parse_option)
expect(command.instance_variable_get(:@grammar_file)).to match(/command\/basic\.y/)
end
end

context "file name is specified after '-'" do
it "@grammar_file is file name" do
command = Lrama::Command.new(["-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@grammar_file)).to eq "test.y"
end
end
end

describe "@outfile" do
context "output option is not passed" do
it "@outfile is default value" do
command = Lrama::Command.new(["-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@outfile)).to eq "y.tab.c"
end
end

context "output option is passed" do
it "@outfile is same with passed value" do
command = Lrama::Command.new(["-o", "parse.c", "-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@outfile)).to eq "parse.c"
end
end
end

describe "@header_file" do
context "header file name is not passed" do
context "outfile option is passed" do
it "@header_file is set based on outfile" do
command = Lrama::Command.new(["-h", "-o", "parse.c", "-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@header_file)).to eq "./parse.h"
end
end

context "outfile option is not passed" do
it "@header_file is set based on outfile default value" do
command = Lrama::Command.new(["-h", "-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@header_file)).to eq "./y.tab.h"
end
end
end

context "header file name is passed" do
it "@header_file is same with passed value" do
command = Lrama::Command.new(["-hparse.h", "-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@header_file)).to eq "parse.h"
end
end
end

describe "@report_file" do
context "report file name is not passed" do
it "@report_file is set based on grammar file name" do
command = Lrama::Command.new(["--report=all", fixture_path("command/basic.y")])
command.send(:parse_option)
expect(command.instance_variable_get(:@report_file)).to match(/command\/basic\.output/)

command = Lrama::Command.new(["--report=all", "-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@report_file)).to eq "./test.output"
end
end

context "report file name is passed" do
it "@report_file is same with passed value" do
command = Lrama::Command.new(["--report-file=report.output", fixture_path("command/basic.y")])
command.send(:parse_option)
expect(command.instance_variable_get(:@report_file)).to eq "report.output"

command = Lrama::Command.new(["--report-file=report.output", "-", "test.y"])
command.send(:parse_option)
expect(command.instance_variable_get(:@report_file)).to eq "report.output"
end
end
end
end
2 changes: 1 addition & 1 deletion spec/lrama/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_rules(rules, input, expected)
c_path = File.dirname(f.path) + "/test.c"
obj_path = File.dirname(f.path) + "/test"

Lrama::Command.new.run(%W[-d #{f.path} -o #{c_path}])
Lrama::Command.new(%W[-d #{f.path} -o #{c_path}]).run

`gcc -Wall #{c_path} -o #{obj_path}`

Expand Down

0 comments on commit 44b8cb4

Please sign in to comment.