# 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] " 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) 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?("(") ? "#{val}" : "+#{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