diff options
Diffstat (limited to 'libexec/y2racc')
-rwxr-xr-x | libexec/y2racc | 339 |
1 files changed, 0 insertions, 339 deletions
diff --git a/libexec/y2racc b/libexec/y2racc deleted file mode 100755 index 7933f94153..0000000000 --- a/libexec/y2racc +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/local/bin/ruby -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -require 'racc/info' -require 'strscan' -require 'forwardable' -require 'optparse' - -def main - @with_action = true - @with_header = false - @with_usercode = false - cname = 'MyParser' - input = nil - output = nil - parser = OptionParser.new - parser.banner = "Usage: #{File.basename($0)} [-Ahu] [-c <classname>] [-o <filename>] <input>" - parser.on('-o', '--output=FILENAME', 'output file name [<input>.racc]') {|name| - output = name - } - parser.on('-c', '--classname=NAME', "Name of the parser class. [#{cname}]") {|name| - cname = name - } - parser.on('-A', '--without-action', 'Does not include actions.') { - @with_action = false - } - parser.on('-h', '--with-header', 'Includes header (%{...%}).') { - @with_header = true - } - parser.on('-u', '--with-user-code', 'Includes user code.') { - @with_usercode = true - } - parser.on('--version', 'Prints version and quit.') { - puts "y2racc version #{Racc::Version}" - exit 0 - } - parser.on('--copyright', 'Prints copyright and quit.') { - puts Racc::Copyright - exit 0 - } - parser.on('--help', 'Prints this message and quit.') { - puts parser.help - exit 1 - } - begin - parser.parse! - rescue OptionParser::ParseError => err - $stderr.puts err.message - $stderr.puts parser.help - exit 1 - end - if ARGV.empty? - $stderr.puts 'no input' - exit 1 - end - if ARGV.size > 1 - $stderr.puts 'too many input' - exit 1 - end - input = ARGV[0] - - begin - result = YaccFileParser.parse_file(input) - File.open(output || "#{input}.racc", 'w') {|f| - convert cname, result, f - } - rescue SystemCallError => err - $stderr.puts err.message - exit 1 - end -end - -def convert(classname, result, f) - init_indent = 'token'.size - f.puts %<# Converted from "#{result.filename}" by y2racc version #{Racc::Version}> - f.puts - f.puts "class #{classname}" - unless result.terminals.empty? - f.puts - f.print 'token' - columns = init_indent - result.terminals.each do |t| - if columns > 60 - f.puts - f.print ' ' * init_indent - columns = init_indent - end - columns += f.write(" #{t}") - end - f.puts - end - unless result.precedence_table.empty? - f.puts - f.puts 'preclow' - result.precedence_table.each do |assoc, toks| - f.printf " %-8s %s\n", assoc, toks.join(' ') unless toks.empty? - end - f.puts 'prechigh' - end - if result.start - f.puts - f.puts "start #{@start}" - end - - f.puts - f.puts 'rule' - texts = @with_action ? result.grammar : result.grammar_without_actions - texts.each do |text| - f.print text - end - - if @with_header and result.header - f.puts - f.puts '---- header' - f.puts result.header - end - if @with_usercode and result.usercode - f.puts - f.puts '---- footer' - f.puts result.usercode - end -end - -class ParseError < StandardError; end - -class StringScanner_withlineno - def initialize(src) - @s = StringScanner.new(src) - @lineno = 1 - end - - extend Forwardable - def_delegator "@s", :eos? - def_delegator "@s", :rest - - attr_reader :lineno - - def scan(re) - advance_lineno(@s.scan(re)) - end - - def scan_until(re) - advance_lineno(@s.scan_until(re)) - end - - def skip(re) - str = advance_lineno(@s.scan(re)) - str ? str.size : nil - end - - def getch - advance_lineno(@s.getch) - end - - private - - def advance_lineno(str) - @lineno += str.count("\n") if str - str - end -end - -class YaccFileParser - - Result = Struct.new(:terminals, :precedence_table, :start, - :header, :grammar, :usercode, :filename) - class Result # reopen - def initialize - super - self.terminals = [] - self.precedence_table = [] - self.start = nil - self.grammar = [] - self.header = nil - self.usercode = nil - self.filename = nil - end - - def grammar_without_actions - grammar().map {|text| text[0,1] == '{' ? '{}' : text } - end - end - - def YaccFileParser.parse_file(filename) - new().parse(File.read(filename), filename) - end - - def parse(src, filename = '-') - @result = Result.new - @filename = filename - @result.filename = filename - s = StringScanner_withlineno.new(src) - parse_header s - parse_grammar s - @result - end - - private - - COMMENT = %r</\*[^*]*\*+(?:[^/*][^*]*\*+)*/> - CHAR = /'((?:[^'\\]+|\\.)*)'/ - STRING = /"((?:[^"\\]+|\\.)*)"/ - - def parse_header(s) - skip_until_percent s - until s.eos? - case - when t = s.scan(/left/) - @result.precedence_table.push ['left', scan_symbols(s)] - when t = s.scan(/right/) - @result.precedence_table.push ['right', scan_symbols(s)] - when t = s.scan(/nonassoc/) - @result.precedence_table.push ['nonassoc', scan_symbols(s)] - when t = s.scan(/token/) - list = scan_symbols(s) - list.shift if /\A<(.*)>\z/ =~ list[0] - @result.terminals.concat list - when t = s.scan(/start/) - @result.start = scan_symbols(s)[0] - when s.skip(%r<(?: - type | union | expect | thong | binary | - semantic_parser | pure_parser | no_lines | - raw | token_table - )\b>x) - skip_until_percent s - when s.skip(/\{/) # header (%{...%}) - str = s.scan_until(/\%\}/) - str.chop! - str.chop! - @result.header = str - skip_until_percent s - when s.skip(/\%/) # grammar (%%...) - return - else - raise ParseError, "#{@filename}:#{s.lineno}: scan error" - end - end - end - - def skip_until_percent(s) - until s.eos? - s.skip /[^\%\/]+/ - next if s.skip(COMMENT) - return if s.getch == '%' - end - end - - def scan_symbols(s) - list = [] - until s.eos? - s.skip /\s+/ - if s.skip(COMMENT) - ; - elsif t = s.scan(CHAR) - list.push t - elsif t = s.scan(STRING) - list.push t - elsif s.skip(/\%/) - break - elsif t = s.scan(/\S+/) - list.push t - else - raise ParseError, "#{@filename}:#{@lineno}: scan error" - end - end - list - end - - def parse_grammar(s) - buf = [] - until s.eos? - if t = s.scan(/[^%'"{\/]+/) - buf.push t - break if s.eos? - end - if s.skip(/\{/) - buf.push scan_action(s) - elsif t = s.scan(/'(?:[^'\\]+|\\.)*'/) then buf.push t - elsif t = s.scan(/"(?:[^"\\]+|\\.)*"/) then buf.push t - elsif t = s.scan(COMMENT) then buf.push t - elsif s.skip(/%prec\b/) then buf.push '=' - elsif s.skip(/%%/) - @result.usercode = s.rest - break - else - buf.push s.getch - end - end - @result.grammar = buf - end - - def scan_action(s) - buf = '{' - nest = 1 - until s.eos? - if t = s.scan(%r<[^/{}'"]+>) - buf << t - break if s.eos? - elsif t = s.scan(COMMENT) - buf << t - elsif t = s.scan(CHAR) - buf << t - elsif t = s.scan(STRING) - buf << t - else - c = s.getch - buf << c - case c - when '{' - nest += 1 - when '}' - nest -= 1 - return buf if nest == 0 - end - end - end - $stderr.puts "warning: unterminated action in #{@filename}" - buf - end - -end - -unless Object.method_defined?(:funcall) - class Object - alias funcall __send__ - end -end - - -main |