diff options
Diffstat (limited to 'tool/lrama/lib/lrama/command.rb')
-rw-r--r-- | tool/lrama/lib/lrama/command.rb | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/tool/lrama/lib/lrama/command.rb b/tool/lrama/lib/lrama/command.rb new file mode 100644 index 0000000000..71369de8ef --- /dev/null +++ b/tool/lrama/lib/lrama/command.rb @@ -0,0 +1,144 @@ +require 'optparse' + +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 + + 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 + + if !grammar_file + puts "File should be specified\n" + exit 1 + end + + Report::Duration.enable if trace_opts[:time] + + warning = Lrama::Warning.new + y = File.read(grammar_file) + grammar = Lrama::Parser.new(y).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 + reporter = Lrama::StatesReporter.new(states) + File.open(report_file, "w+") do |f| + reporter.report(f, **report_opts) + end + end + + 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, + context: context, + grammar: grammar, + ).render + end + + if warning.has_error? + exit 1 + end + end + + private + + def validate_report(report) + bison_list = %w[states itemsets lookaheads solved counterexamples cex all none] + others = %w[verbose] + list = bison_list + others + not_supported = %w[counterexamples cex none] + h = { grammar: true } + + report.each do |r| + if list.include?(r) && !not_supported.include?(r) + h[r.to_sym] = true + else + raise "Invalid report option \"#{r}\"." + end + end + + if h[:all] + (bison_list - not_supported).each do |r| + h[r.to_sym] = true + end + + h.delete(:all) + end + + return h + end + + def validate_trace(trace) + list = %w[ + none locations scan parse automaton bitsets + closure grammar resource sets muscles tools + m4-early m4 skeleton time ielr cex all + ] + h = {} + + trace.each do |t| + if list.include?(t) + h[t.to_sym] = true + else + raise "Invalid trace option \"#{t}\"." + end + end + + return h + end + end +end |