зеркало из https://github.com/github/ruby.git
Removed the old executables of racc
[ruby-core:93516][Feature #15982] https://github.com/ruby/racc/pull/123
This commit is contained in:
Родитель
e1c363f847
Коммит
a6864f6d2f
27
bin/racc2y
27
bin/racc2y
|
@ -1,27 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by RubyGems.
|
||||
#
|
||||
# The application 'racc' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
version = ">= 0.a"
|
||||
|
||||
if ARGV.first
|
||||
str = ARGV.first
|
||||
str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
|
||||
if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
|
||||
version = $1
|
||||
ARGV.shift
|
||||
end
|
||||
end
|
||||
|
||||
if Gem.respond_to?(:activate_bin_path)
|
||||
load Gem.activate_bin_path('racc', 'racc2y', version)
|
||||
else
|
||||
gem "racc", version
|
||||
load Gem.bin_path("racc", "racc2y", version)
|
||||
end
|
27
bin/y2racc
27
bin/y2racc
|
@ -1,27 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by RubyGems.
|
||||
#
|
||||
# The application 'racc' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
version = ">= 0.a"
|
||||
|
||||
if ARGV.first
|
||||
str = ARGV.first
|
||||
str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
|
||||
if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
|
||||
version = $1
|
||||
ARGV.shift
|
||||
end
|
||||
end
|
||||
|
||||
if Gem.respond_to?(:activate_bin_path)
|
||||
load Gem.activate_bin_path('racc', 'y2racc', version)
|
||||
else
|
||||
gem "racc", version
|
||||
load Gem.bin_path("racc", "y2racc", version)
|
||||
end
|
195
libexec/racc2y
195
libexec/racc2y
|
@ -1,195 +0,0 @@
|
|||
#!/usr/local/bin/ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Copyright (c) 1999-2006 Minero Aoki
|
||||
#
|
||||
# This program is feee 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 LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
require 'racc/grammarfileparser'
|
||||
require 'racc/info'
|
||||
require 'optparse'
|
||||
|
||||
def main
|
||||
@with_action = true
|
||||
with_header = false
|
||||
with_inner = false
|
||||
with_footer = false
|
||||
output = nil
|
||||
parser = OptionParser.new
|
||||
parser.banner = "Usage: #{File.basename($0)} [-AHIF] [-oFILENAME] GRAMMARFILE"
|
||||
parser.on('-o', '--output=FILENAME', 'output file name [<input>.yacc]') {|name|
|
||||
output = name
|
||||
}
|
||||
parser.on('-A', '--without-action', 'Does not include actions.') {
|
||||
@with_action = false
|
||||
}
|
||||
parser.on('-H', '--with-header', 'Includes header part.') {
|
||||
with_header = true
|
||||
}
|
||||
parser.on('-I', '--with-inner', 'Includes inner part.') {
|
||||
with_inner = true
|
||||
}
|
||||
parser.on('-F', '--with-footer', 'Includes footer part.') {
|
||||
with_footer = true
|
||||
}
|
||||
parser.on('--version', 'Prints version and quit.') {
|
||||
puts "racc2y 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 file"
|
||||
exit 1
|
||||
end
|
||||
unless ARGV.size == 1
|
||||
$stderr.puts "too many inputs"
|
||||
exit 1
|
||||
end
|
||||
input = ARGV[0]
|
||||
|
||||
begin
|
||||
result = Racc::GrammarFileParser.parse_file(input)
|
||||
result.grammar.init
|
||||
File.open(output || "#{input}.yacc", 'w') {|f|
|
||||
f.puts "/* generated from #{input} */"
|
||||
if with_header
|
||||
f.puts
|
||||
f.puts '%{'
|
||||
print_user_codes f, result.params.header
|
||||
f.puts '%}'
|
||||
end
|
||||
f.puts
|
||||
print_terminals f, result.grammar
|
||||
f.puts
|
||||
print_precedence_table f, precedence_table(result.grammar)
|
||||
f.puts
|
||||
f.puts '%%'
|
||||
print_grammar f, result.grammar
|
||||
f.puts '%%'
|
||||
if with_inner
|
||||
f.puts '/*---- inner ----*/'
|
||||
print_user_codes f, result.params.inner
|
||||
end
|
||||
if with_footer
|
||||
f.puts '/*---- footer ----*/'
|
||||
print_user_codes f, result.params.footer
|
||||
end
|
||||
}
|
||||
rescue SystemCallError => err
|
||||
$stderr.puts err.message
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
def print_terminals(f, grammar)
|
||||
init_indent = '%token'.size
|
||||
f.print '%token'
|
||||
columns = init_indent
|
||||
grammar.symboltable.each_terminal do |t|
|
||||
next unless t.terminal?
|
||||
next if t.dummy?
|
||||
next if t == grammar.symboltable.anchor
|
||||
next if t == grammar.symboltable.error
|
||||
unless t.value.kind_of?(String)
|
||||
if columns > 60
|
||||
f.puts
|
||||
f.print ' ' * init_indent
|
||||
columns = init_indent
|
||||
end
|
||||
columns += f.write(" #{yacc_symbol(t)}")
|
||||
end
|
||||
end
|
||||
f.puts
|
||||
end
|
||||
|
||||
def precedence_table(grammar)
|
||||
table = []
|
||||
grammar.symboltable.select {|sym| sym.precedence }.each do |sym|
|
||||
(table[sym.prec] ||= [sym.assoc]).push sym
|
||||
end
|
||||
table.compact
|
||||
end
|
||||
|
||||
def print_precedence_table(f, table)
|
||||
return if table.empty?
|
||||
f.puts '/* precedance table */'
|
||||
table.each do |syms|
|
||||
assoc = syms.shift
|
||||
f.printf '%%%-8s ', assoc.to_s.downcase
|
||||
f.puts syms.map {|s| yacc_symbol(s) }.join(' ')
|
||||
end
|
||||
f.puts
|
||||
end
|
||||
|
||||
def print_grammar(f, grammar)
|
||||
prev_target = nil
|
||||
indent = 10
|
||||
embactions = []
|
||||
grammar.each do |rule|
|
||||
if rule.target.dummy?
|
||||
embactions.push rule.action unless rule.action.empty?
|
||||
next
|
||||
end
|
||||
if rule.target == prev_target
|
||||
f.print ' ' * indent, '|'
|
||||
else
|
||||
prev_target = rule.target
|
||||
f.printf "\n%-10s:", yacc_symbol(prev_target)
|
||||
end
|
||||
rule.symbols.each do |s|
|
||||
if s.dummy? # target of dummy rule for embedded action
|
||||
f.puts
|
||||
print_action f, embactions.shift, indent
|
||||
f.print ' ' * (indent + 1)
|
||||
else
|
||||
f.print ' ', yacc_symbol(s)
|
||||
end
|
||||
end
|
||||
if rule.specified_prec
|
||||
f.print ' %prec ', yacc_symbol(rule.specified_prec)
|
||||
end
|
||||
f.puts
|
||||
unless rule.action.empty?
|
||||
print_action f, rule.action, indent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def print_action(f, action, indent)
|
||||
return unless @with_action
|
||||
f.print ' ' * (indent + 4), "{\n"
|
||||
f.print ' ' * (indent + 6), action.source.text.strip, "\n"
|
||||
f.print ' ' * (indent + 4) , "}\n"
|
||||
end
|
||||
|
||||
def print_user_codes(f, srcs)
|
||||
return if srcs.empty?
|
||||
srcs.each do |src|
|
||||
f.puts src.text
|
||||
end
|
||||
end
|
||||
|
||||
def yacc_symbol(s)
|
||||
s.to_s.gsub('"', "'")
|
||||
end
|
||||
|
||||
main
|
339
libexec/y2racc
339
libexec/y2racc
|
@ -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
|
Загрузка…
Ссылка в новой задаче