diff options
Diffstat (limited to 'ext/ripper/tools/preproc.rb')
| -rw-r--r-- | ext/ripper/tools/preproc.rb | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb new file mode 100644 index 0000000000..5e8a6e0cb5 --- /dev/null +++ b/ext/ripper/tools/preproc.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true +# $Id$ + +require 'optparse' + +def main + output = nil + template = nil + parser = OptionParser.new + parser.banner = "Usage: #{File.basename($0)} [--output=PATH] [--template=PATH] <parse.y>" + parser.on('--output=PATH', 'An output file.') {|path| + output = path + } + parser.on('--template=PATH', 'An template file.') {|path| + template = path + } + parser.on('--help', 'Prints this message and quit.') { + puts parser.help + exit true + } + begin + parser.parse! + rescue OptionParser::ParseError => err + warn err.message + abort parser.help + end + out = "".dup + if ARGV[0] == "-" + unless ARGV.size == 2 + abort "wrong number of arguments (#{ARGV.size} for 2)" + end + process STDIN, out, ARGV[1], template + else + unless ARGV.size == 1 + abort "wrong number of arguments (#{ARGV.size} for 1)" + end + File.open(ARGV[0]) {|f| + process f, out, ARGV[0], template + } + end + if output + File.write(output, out) + else + print out + end +end + +def process(f, out, path, template) + prelude f, out + grammar f, out + usercode f, out, path, template +end + +require_relative 'dsl' + +def generate_line(f, out) + while line = f.gets + case + when gen = DSL.line?(line, f.lineno) + out << gen.generate << "\n" + when line.start_with?("%%") + out << "%%\n" + break + else + out << yield(line) + end + end +end + +def prelude(f, out) + @exprs = {} + generate_line(f, out) do |line| + if (/^enum lex_state_(?:bits|e) \{/ =~ line)..(/^\}/ =~ line) + case line + when /^\s*(EXPR_\w+),\s+\/\*(.+)\*\// + @exprs[$1.chomp("_bit")] = $2.strip + when /^\s*(EXPR_\w+)\s+=\s+(.+)$/ + name = $1 + val = $2.chomp(",") + @exprs[name] = "equals to " + (val.start_with?("(") ? "<tt>#{val}</tt>" : "+#{val}+") + end + end + line + end +end + +def grammar(f, out) + generate_line(f, out) do |line| + case line + when %r</\*%%%\*/> + "#if 0\n" + when %r</\*%> + "#endif\n" + when %r<%\*/> + "\n" + else + line + end + end +end + +def usercode(f, out, path, template) + require 'erb' + lineno = nil + src = nil + compiler = ERB::Compiler.new('%-') + compiler.put_cmd = compiler.insert_cmd = "out.<<" + + if template + File.open(template) do |f| + out.clear + lineno = f.lineno + src, = compiler.compile(f.read) + path = template + end + else + lineno = f.lineno + src, = compiler.compile(f.read) + end + + eval(src, binding, path, lineno) +end + +main |
