racc 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitattributes +2 -0
- data/.gitignore +7 -0
- data/COPYING +515 -0
- data/ChangeLog +846 -0
- data/DEPENDS +4 -0
- data/README.en.rdoc +86 -0
- data/README.ja.rdoc +96 -0
- data/Rakefile +15 -0
- data/TODO +5 -0
- data/bin/racc +308 -0
- data/bin/racc2y +195 -0
- data/bin/y2racc +339 -0
- data/doc/en/NEWS.en.rdoc +282 -0
- data/doc/en/command.en.html +78 -0
- data/doc/en/debug.en.rdoc +20 -0
- data/doc/en/grammar.en.rdoc +230 -0
- data/doc/en/index.en.html +10 -0
- data/doc/en/parser.en.rdoc +74 -0
- data/doc/en/usage.en.html +92 -0
- data/doc/ja/NEWS.ja.rdoc +307 -0
- data/doc/ja/command.ja.html +94 -0
- data/doc/ja/debug.ja.rdoc +36 -0
- data/doc/ja/grammar.ja.rdoc +348 -0
- data/doc/ja/index.ja.html +10 -0
- data/doc/ja/parser.ja.rdoc +125 -0
- data/doc/ja/usage.ja.html +414 -0
- data/ext/racc/cparse/MANIFEST +4 -0
- data/ext/racc/cparse/cparse.c +824 -0
- data/ext/racc/cparse/depend +1 -0
- data/ext/racc/cparse/extconf.rb +7 -0
- data/fastcache/extconf.rb +2 -0
- data/fastcache/fastcache.c +185 -0
- data/lib/racc.rb +6 -0
- data/lib/racc/compat.rb +40 -0
- data/lib/racc/debugflags.rb +59 -0
- data/lib/racc/exception.rb +15 -0
- data/lib/racc/grammar.rb +1115 -0
- data/lib/racc/grammarfileparser.rb +559 -0
- data/lib/racc/info.rb +16 -0
- data/lib/racc/iset.rb +91 -0
- data/lib/racc/logfilegenerator.rb +214 -0
- data/lib/racc/parser.rb +439 -0
- data/lib/racc/parserfilegenerator.rb +511 -0
- data/lib/racc/pre-setup +13 -0
- data/lib/racc/sourcetext.rb +34 -0
- data/lib/racc/state.rb +971 -0
- data/lib/racc/statetransitiontable.rb +316 -0
- data/lib/racc/static.rb +5 -0
- data/misc/dist.sh +31 -0
- data/sample/array.y +67 -0
- data/sample/array2.y +59 -0
- data/sample/calc-ja.y +66 -0
- data/sample/calc.y +65 -0
- data/sample/conflict.y +15 -0
- data/sample/hash.y +60 -0
- data/sample/lalr.y +17 -0
- data/sample/lists.y +57 -0
- data/sample/syntax.y +46 -0
- data/sample/yyerr.y +46 -0
- data/setup.rb +1587 -0
- data/tasks/doc.rb +12 -0
- data/tasks/email.rb +55 -0
- data/tasks/file.rb +37 -0
- data/tasks/gem.rb +37 -0
- data/tasks/test.rb +16 -0
- data/test/assets/chk.y +126 -0
- data/test/assets/conf.y +16 -0
- data/test/assets/digraph.y +29 -0
- data/test/assets/echk.y +118 -0
- data/test/assets/err.y +60 -0
- data/test/assets/expect.y +7 -0
- data/test/assets/firstline.y +4 -0
- data/test/assets/ichk.y +102 -0
- data/test/assets/intp.y +546 -0
- data/test/assets/mailp.y +437 -0
- data/test/assets/newsyn.y +25 -0
- data/test/assets/noend.y +4 -0
- data/test/assets/nonass.y +41 -0
- data/test/assets/normal.y +27 -0
- data/test/assets/norule.y +4 -0
- data/test/assets/nullbug1.y +25 -0
- data/test/assets/nullbug2.y +15 -0
- data/test/assets/opt.y +123 -0
- data/test/assets/percent.y +35 -0
- data/test/assets/recv.y +97 -0
- data/test/assets/rrconf.y +14 -0
- data/test/assets/scan.y +72 -0
- data/test/assets/syntax.y +50 -0
- data/test/assets/unterm.y +5 -0
- data/test/assets/useless.y +12 -0
- data/test/assets/yyerr.y +46 -0
- data/test/bench.y +36 -0
- data/test/helper.rb +88 -0
- data/test/infini.y +8 -0
- data/test/scandata/brace +7 -0
- data/test/scandata/gvar +1 -0
- data/test/scandata/normal +4 -0
- data/test/scandata/percent +18 -0
- data/test/scandata/slash +10 -0
- data/test/src.intp +34 -0
- data/test/start.y +20 -0
- data/test/test_chk_y.rb +51 -0
- data/test/test_grammar_file_parser.rb +15 -0
- data/test/test_racc_command.rb +155 -0
- data/test/test_scan_y.rb +51 -0
- data/test/testscanner.rb +51 -0
- data/web/racc.en.rhtml +42 -0
- data/web/racc.ja.rhtml +51 -0
- metadata +166 -0
data/DEPENDS
ADDED
data/README.en.rdoc
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
= Racc
|
2
|
+
|
3
|
+
* http://i.loveruby.net/en/projects/racc/
|
4
|
+
* http://racc.rubyforge.org/
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Racc is a LALR(1) parser generator.
|
9
|
+
It is written in Ruby itself, and generates Ruby program.
|
10
|
+
|
11
|
+
NOTE: Ruby 1.8.x comes with Racc runtime module. You
|
12
|
+
can run your parsers generated by racc 1.4.x out of the
|
13
|
+
box.
|
14
|
+
|
15
|
+
|
16
|
+
== Requirement
|
17
|
+
|
18
|
+
* Ruby 1.8.x or later.
|
19
|
+
(*) make and C compiler.
|
20
|
+
|
21
|
+
|
22
|
+
== Installation
|
23
|
+
|
24
|
+
gem install:
|
25
|
+
|
26
|
+
$ gem install racc
|
27
|
+
|
28
|
+
setup.rb install:
|
29
|
+
|
30
|
+
Type this in the top directory of the extracted archive:
|
31
|
+
|
32
|
+
$ ruby setup.rb config
|
33
|
+
$ ruby setup.rb setup
|
34
|
+
($ su)
|
35
|
+
# ruby setup.rb install
|
36
|
+
|
37
|
+
You can install Racc into your favorite directory by giving
|
38
|
+
options to setup.rb. e.g.
|
39
|
+
|
40
|
+
$ ruby setup.rb config --prefix=/usr
|
41
|
+
|
42
|
+
For details, try "ruby setup.rb --help".
|
43
|
+
|
44
|
+
|
45
|
+
If you don't have C Compiler
|
46
|
+
----------------------------
|
47
|
+
|
48
|
+
You can install Racc without C compilers. Type following
|
49
|
+
command in config phase.
|
50
|
+
|
51
|
+
$ ruby setup.rb config --without-ext
|
52
|
+
|
53
|
+
|
54
|
+
== Testing Racc
|
55
|
+
|
56
|
+
Racc comes with simple calculator. To compile this, on shell:
|
57
|
+
|
58
|
+
$ racc -o calc calc.y
|
59
|
+
|
60
|
+
This process costs few seconds (or less). Then type:
|
61
|
+
|
62
|
+
$ ruby calc
|
63
|
+
|
64
|
+
... Does it works?
|
65
|
+
For details of Racc, see HTML documents placed under 'doc.en/'
|
66
|
+
and sample grammer files under 'sample/'.
|
67
|
+
|
68
|
+
|
69
|
+
== License
|
70
|
+
|
71
|
+
Racc is distributed under the terms of the GNU Lesser General
|
72
|
+
Public License version 2. Note that you do NOT need to follow
|
73
|
+
LGPL for your own parser (racc outputs). You can provide those
|
74
|
+
files under any licenses you want.
|
75
|
+
|
76
|
+
|
77
|
+
== Bug Reports
|
78
|
+
|
79
|
+
Any kind of bug reports are welcome.
|
80
|
+
If you find a bug of Racc, please email me. Your grammer file,
|
81
|
+
debug output genereted by "racc -g", are helpful.
|
82
|
+
|
83
|
+
|
84
|
+
Minero Aoki
|
85
|
+
aamine@loveruby.net
|
86
|
+
http://i.loveruby.net
|
data/README.ja.rdoc
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
= Racc
|
2
|
+
|
3
|
+
* http://i.loveruby.net/en/projects/racc/
|
4
|
+
* http://racc.rubyforge.org/
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Racc は LALR(1) パーサジェネレータです。
|
9
|
+
yacc の Ruby 版に相当します。
|
10
|
+
|
11
|
+
NOTE:
|
12
|
+
Ruby 1.8.0 からは Racc のランタイムが標準添付されているので、
|
13
|
+
Racc で生成したパーサを安心して配布できます。また Ruby 1.6 系に
|
14
|
+
対応させたい場合は racc -E で生成してください。
|
15
|
+
|
16
|
+
|
17
|
+
== 必要環境
|
18
|
+
|
19
|
+
* Ruby 1.8 以降
|
20
|
+
(*) C コンパイラと make
|
21
|
+
|
22
|
+
|
23
|
+
== インストール
|
24
|
+
|
25
|
+
gem インストール:
|
26
|
+
|
27
|
+
$ gem install racc
|
28
|
+
|
29
|
+
setup.rb インストル:
|
30
|
+
|
31
|
+
パッケージのトップディレクトリで次のように入力してください。
|
32
|
+
($ は通常ユーザ、# はルートのプロンプトです)
|
33
|
+
|
34
|
+
$ ruby setup.rb config
|
35
|
+
$ ruby setup.rb setup
|
36
|
+
($ su)
|
37
|
+
# ruby setup.rb install
|
38
|
+
|
39
|
+
これで通常のパスに Racc がインストールされます。自分の好き
|
40
|
+
なディレクトリにインストールしたいときは、setup.rb config に
|
41
|
+
各種オプションをつけて実行してください。オプションのリストは
|
42
|
+
|
43
|
+
$ ruby setup.rb --help
|
44
|
+
|
45
|
+
で見られます。
|
46
|
+
|
47
|
+
|
48
|
+
コンパイラがない場合
|
49
|
+
--------------------
|
50
|
+
|
51
|
+
config を以下のようにすれば、拡張モジュールなしで
|
52
|
+
インストールできます。
|
53
|
+
|
54
|
+
$ ruby setup.rb config --without-ext
|
55
|
+
|
56
|
+
|
57
|
+
== テスト
|
58
|
+
|
59
|
+
sample/ 以下にいくつか Racc の文法ファイルのサンプルが用意
|
60
|
+
してあります。動くのも動かないのもありますが、少なくとも
|
61
|
+
calc-ja.y は動くのでこれを処理してみましょう。Racc をインス
|
62
|
+
トールしたあと
|
63
|
+
|
64
|
+
$ racc -ocalc.rb calc-ja.y
|
65
|
+
|
66
|
+
として下さい。処理は一瞬から数秒で終わるので、
|
67
|
+
|
68
|
+
$ ruby calc.rb
|
69
|
+
|
70
|
+
を実行してください。ちゃんと動いてますか?
|
71
|
+
|
72
|
+
Racc の文法など詳しいことは doc.ja/ ディレクトリ以下の HTML を
|
73
|
+
見てください。
|
74
|
+
|
75
|
+
|
76
|
+
== ライセンス
|
77
|
+
|
78
|
+
このパッケージに付属するファイルの著作権は青木峰郎が保持します。
|
79
|
+
ライセンスは GNU Lesser General Public License (LGPL) version 2
|
80
|
+
です。ただしユーザが書いた規則ファイルや、Racc がそこから生成し
|
81
|
+
た Ruby スクリプトはその対象外です。好きなライセンスで配布して
|
82
|
+
ください。
|
83
|
+
|
84
|
+
|
85
|
+
== バグなど
|
86
|
+
|
87
|
+
Racc を使っていてバグらしき現象に遭遇したら、下記のアドレスまで
|
88
|
+
メールをください。作者にはバグを修正する義務はありませんがその
|
89
|
+
意思はあります。また、そのときはできるだけバグを再現できる文法
|
90
|
+
ファイルを付けてください。
|
91
|
+
|
92
|
+
|
93
|
+
青木峰郎(あおきみねろう)
|
94
|
+
aamine@loveruby.net
|
95
|
+
http://i.loveruby.net
|
96
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/clean'
|
6
|
+
|
7
|
+
require 'lib/racc/parser'
|
8
|
+
|
9
|
+
require 'tasks/file'
|
10
|
+
require 'tasks/gem'
|
11
|
+
require 'tasks/test'
|
12
|
+
require 'tasks/doc'
|
13
|
+
require 'tasks/email'
|
14
|
+
|
15
|
+
task :default => :test
|
data/TODO
ADDED
data/bin/racc
ADDED
@@ -0,0 +1,308 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# $Id$
|
4
|
+
#
|
5
|
+
# Copyright (c) 1999-2006 Minero Aoki
|
6
|
+
#
|
7
|
+
# This program is free software.
|
8
|
+
# You can distribute/modify this program under the terms of
|
9
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
10
|
+
# For details of LGPL, see the file "COPYING".
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'racc/static'
|
14
|
+
require 'optparse'
|
15
|
+
|
16
|
+
def main
|
17
|
+
output = nil
|
18
|
+
debug_parser = false
|
19
|
+
make_logfile = false
|
20
|
+
logfilename = nil
|
21
|
+
make_executable = false
|
22
|
+
rubypath = nil
|
23
|
+
embed_runtime = false
|
24
|
+
debug_flags = Racc::DebugFlags.new
|
25
|
+
line_convert = true
|
26
|
+
line_convert_all = false
|
27
|
+
omit_action_call = true
|
28
|
+
superclass = nil
|
29
|
+
check_only = false
|
30
|
+
verbose = false
|
31
|
+
profiler = RaccProfiler.new(false)
|
32
|
+
|
33
|
+
parser = OptionParser.new
|
34
|
+
parser.banner = "Usage: #{File.basename($0)} [options] <input>"
|
35
|
+
parser.on('-o', '--output-file=PATH',
|
36
|
+
'output file name [<input>.tab.rb]') {|name|
|
37
|
+
output = name
|
38
|
+
}
|
39
|
+
parser.on('-t', '--debug', 'Outputs debugging parser.') {|fl|
|
40
|
+
debug_parser = fl
|
41
|
+
}
|
42
|
+
parser.on('-g', 'Equivalent to -t (obsolete).') {|fl|
|
43
|
+
$stderr.puts "racc -g is obsolete. Use racc -t instead." if $VERBOSE
|
44
|
+
debug_parser = fl
|
45
|
+
}
|
46
|
+
parser.on('-v', '--verbose',
|
47
|
+
'Creates <filename>.output log file.') {|fl|
|
48
|
+
make_logfile = fl
|
49
|
+
}
|
50
|
+
parser.on('-O', '--log-file=PATH',
|
51
|
+
'Log file name [<input>.output]') {|path|
|
52
|
+
make_logfile = true
|
53
|
+
logfilename = path
|
54
|
+
}
|
55
|
+
parser.on('-e', '--executable [RUBYPATH]', 'Makes executable parser.') {|path|
|
56
|
+
executable = true
|
57
|
+
rubypath = (path == 'ruby' ? nil : path)
|
58
|
+
}
|
59
|
+
parser.on('-E', '--embedded', "Embeds Racc runtime in output.") {
|
60
|
+
embed_runtime = true
|
61
|
+
}
|
62
|
+
parser.on('--line-convert-all', 'Converts line numbers of user codes.') {
|
63
|
+
line_convert_all = true
|
64
|
+
}
|
65
|
+
parser.on('-l', '--no-line-convert', 'Never convert line numbers.') {
|
66
|
+
line_convert = false
|
67
|
+
line_convert_all = false
|
68
|
+
}
|
69
|
+
parser.on('-a', '--no-omit-actions', 'Never omit actions.') {
|
70
|
+
omit_action_call = false
|
71
|
+
}
|
72
|
+
parser.on('--superclass=CLASSNAME',
|
73
|
+
'Uses CLASSNAME instead of Racc::Parser.') {|name|
|
74
|
+
superclass = name
|
75
|
+
}
|
76
|
+
parser.on('--runtime=FEATURE',
|
77
|
+
"Uses FEATURE instead of 'racc/parser'") {|feat|
|
78
|
+
runtime = feature
|
79
|
+
}
|
80
|
+
parser.on('-C', '--check-only', 'Checks syntax and quit immediately.') {|fl|
|
81
|
+
check_only = fl
|
82
|
+
}
|
83
|
+
parser.on('-S', '--output-status', 'Outputs internal status time to time.') {
|
84
|
+
verbose = true
|
85
|
+
}
|
86
|
+
parser.on('-P', 'Enables generator profile') {
|
87
|
+
profiler = RaccProfiler.new(true)
|
88
|
+
}
|
89
|
+
parser.on('-D flags', "Flags for Racc debugging (do not use).") {|flags|
|
90
|
+
debug_flags = Racc::DebugFlags.parse_option_string(flags)
|
91
|
+
}
|
92
|
+
#parser.on('--no-extensions', 'Run Racc without any Ruby extension.') {
|
93
|
+
# Racc.const_set :Racc_No_Extentions, true
|
94
|
+
#}
|
95
|
+
parser.on('--version', 'Prints version and quit.') {
|
96
|
+
puts "racc version #{Racc::Version}"
|
97
|
+
exit 0
|
98
|
+
}
|
99
|
+
parser.on('--runtime-version', 'Prints runtime version and quit.') {
|
100
|
+
printf "racc runtime version %s (rev. %s); %s\n",
|
101
|
+
Racc::Parser::Racc_Runtime_Version,
|
102
|
+
Racc::Parser::Racc_Runtime_Revision,
|
103
|
+
if Racc::Parser.racc_runtime_type == 'ruby'
|
104
|
+
sprintf('ruby core version %s (rev. %s)',
|
105
|
+
Racc::Parser::Racc_Runtime_Core_Version_R,
|
106
|
+
Racc::Parser::Racc_Runtime_Core_Revision_R)
|
107
|
+
else
|
108
|
+
sprintf('c core version %s (rev. %s)',
|
109
|
+
Racc::Parser::Racc_Runtime_Core_Version_C,
|
110
|
+
Racc::Parser::Racc_Runtime_Core_Revision_C)
|
111
|
+
end
|
112
|
+
exit 0
|
113
|
+
}
|
114
|
+
parser.on('--copyright', 'Prints copyright and quit.') {
|
115
|
+
puts Racc::Copyright
|
116
|
+
exit 0
|
117
|
+
}
|
118
|
+
parser.on('--help', 'Prints this message and quit.') {
|
119
|
+
puts parser.help
|
120
|
+
exit 1
|
121
|
+
}
|
122
|
+
begin
|
123
|
+
parser.parse!
|
124
|
+
rescue OptionParser::ParseError => err
|
125
|
+
$stderr.puts err.message
|
126
|
+
$stderr.puts parser.help
|
127
|
+
exit 1
|
128
|
+
end
|
129
|
+
if ARGV.empty?
|
130
|
+
$stderr.puts 'no input'
|
131
|
+
exit 1
|
132
|
+
end
|
133
|
+
if ARGV.size > 1
|
134
|
+
$stderr.puts 'too many input'
|
135
|
+
exit 1
|
136
|
+
end
|
137
|
+
input = ARGV[0]
|
138
|
+
|
139
|
+
begin
|
140
|
+
$stderr.puts 'Parsing grammar file...' if verbose
|
141
|
+
result = profiler.section('parse') {
|
142
|
+
parser = Racc::GrammarFileParser.new(debug_flags)
|
143
|
+
parser.parse(File.read(input), File.basename(input))
|
144
|
+
}
|
145
|
+
if check_only
|
146
|
+
$stderr.puts 'syntax ok'
|
147
|
+
exit 0
|
148
|
+
end
|
149
|
+
|
150
|
+
$stderr.puts 'Generating LALR states...' if verbose
|
151
|
+
states = profiler.section('nfa') {
|
152
|
+
Racc::States.new(result.grammar).nfa
|
153
|
+
}
|
154
|
+
|
155
|
+
$stderr.puts "Resolving #{states.size} states..." if verbose
|
156
|
+
profiler.section('dfa') {
|
157
|
+
states.dfa
|
158
|
+
}
|
159
|
+
|
160
|
+
$stderr.puts 'Creating parser file...' if verbose
|
161
|
+
params = result.params.dup
|
162
|
+
# Overwrites parameters given by a grammar file with command line options.
|
163
|
+
params.superclass = superclass if superclass
|
164
|
+
params.omit_action_call = true if omit_action_call
|
165
|
+
# From command line option
|
166
|
+
if make_executable
|
167
|
+
params.make_executable = true
|
168
|
+
params.interpreter = rubypath
|
169
|
+
end
|
170
|
+
params.debug_parser = debug_parser
|
171
|
+
params.convert_line = line_convert
|
172
|
+
params.convert_line_all = line_convert_all
|
173
|
+
params.embed_runtime = embed_runtime
|
174
|
+
profiler.section('generation') {
|
175
|
+
generator = Racc::ParserFileGenerator.new(states, params)
|
176
|
+
generator.generate_parser_file(output || make_filename(input, '.tab.rb'))
|
177
|
+
}
|
178
|
+
|
179
|
+
if make_logfile
|
180
|
+
profiler.section('logging') {
|
181
|
+
$stderr.puts 'Creating log file...' if verbose
|
182
|
+
logfilename ||= make_filename(output || File.basename(input), '.output')
|
183
|
+
File.open(logfilename, 'w') {|f|
|
184
|
+
Racc::LogFileGenerator.new(states, debug_flags).output f
|
185
|
+
}
|
186
|
+
}
|
187
|
+
end
|
188
|
+
if debug_flags.status_logging
|
189
|
+
log_useless states.grammar
|
190
|
+
log_conflict states
|
191
|
+
else
|
192
|
+
report_useless states.grammar
|
193
|
+
report_conflict states
|
194
|
+
end
|
195
|
+
|
196
|
+
profiler.report
|
197
|
+
rescue Racc::Error, Errno::ENOENT, Errno::EPERM => err
|
198
|
+
raise if $DEBUG or debug_flags.any?
|
199
|
+
lineno = err.message.slice(/\A\d+:/).to_s
|
200
|
+
$stderr.puts "#{File.basename $0}: #{input}:#{lineno} #{err.message.strip}"
|
201
|
+
exit 1
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def make_filename(path, suffix)
|
206
|
+
path.sub(/(?:\..*?)?\z/, suffix)
|
207
|
+
end
|
208
|
+
|
209
|
+
def report_conflict(states)
|
210
|
+
if states.should_report_srconflict?
|
211
|
+
$stderr.puts "#{states.n_srconflicts} shift/reduce conflicts"
|
212
|
+
end
|
213
|
+
if states.rrconflict_exist?
|
214
|
+
$stderr.puts "#{states.n_rrconflicts} reduce/reduce conflicts"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def log_conflict(states)
|
219
|
+
logging('w') {|f|
|
220
|
+
f.puts "ex#{states.grammar.n_expected_srconflicts}"
|
221
|
+
if states.should_report_srconflict?
|
222
|
+
f.puts "sr#{states.n_srconflicts}"
|
223
|
+
end
|
224
|
+
if states.rrconflict_exist?
|
225
|
+
f.puts "rr#{states.n_rrconflicts}"
|
226
|
+
end
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
230
|
+
def report_useless(grammar)
|
231
|
+
if grammar.useless_nonterminal_exist?
|
232
|
+
$stderr.puts "#{grammar.n_useless_nonterminals} useless nonterminals"
|
233
|
+
end
|
234
|
+
if grammar.useless_rule_exist?
|
235
|
+
$stderr.puts "#{grammar.n_useless_rules} useless rules"
|
236
|
+
end
|
237
|
+
if grammar.start.useless?
|
238
|
+
$stderr.puts 'fatal: start symbol does not derive any sentence'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def log_useless(grammar)
|
243
|
+
logging('a') {|f|
|
244
|
+
if grammar.useless_nonterminal_exist?
|
245
|
+
f.puts "un#{grammar.n_useless_nonterminals}"
|
246
|
+
end
|
247
|
+
if grammar.useless_rule_exist?
|
248
|
+
f.puts "ur#{grammar.n_useless_rules}"
|
249
|
+
end
|
250
|
+
}
|
251
|
+
end
|
252
|
+
|
253
|
+
def logging(mode, &block)
|
254
|
+
File.open("log/#{File.basename(ARGV[0])}", mode, &block)
|
255
|
+
end
|
256
|
+
|
257
|
+
class RaccProfiler
|
258
|
+
def initialize(really)
|
259
|
+
@really = really
|
260
|
+
@log = []
|
261
|
+
unless ::Process.respond_to?(:times)
|
262
|
+
# Ruby 1.6
|
263
|
+
@class = ::Time
|
264
|
+
else
|
265
|
+
@class = ::Process
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def section(name)
|
270
|
+
if @really
|
271
|
+
t1 = @class.times.utime
|
272
|
+
result = yield
|
273
|
+
t2 = @class.times.utime
|
274
|
+
@log.push [name, t2 - t1]
|
275
|
+
result
|
276
|
+
else
|
277
|
+
yield
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def report
|
282
|
+
return unless @really
|
283
|
+
f = $stderr
|
284
|
+
total = cumulative_time()
|
285
|
+
f.puts '--task-----------+--sec------+---%-'
|
286
|
+
@log.each do |name, time|
|
287
|
+
f.printf "%-19s %s %3d%%\n", name, pjust(time,4,4), (time/total*100).to_i
|
288
|
+
end
|
289
|
+
f.puts '-----------------+-----------+-----'
|
290
|
+
f.printf "%-20s%s\n", 'total', pjust(total,4,4)
|
291
|
+
end
|
292
|
+
|
293
|
+
private
|
294
|
+
|
295
|
+
def cumulative_time
|
296
|
+
t = @log.inject(0) {|sum, (name, time)| sum + time }
|
297
|
+
t == 0 ? 0.01 : t
|
298
|
+
end
|
299
|
+
|
300
|
+
def pjust(num, i, j)
|
301
|
+
m = /(\d+)(\.\d+)?/.match(num.to_s)
|
302
|
+
str = m[1].rjust(i)
|
303
|
+
str.concat m[2].ljust(j+1)[0,j+1] if m[2]
|
304
|
+
str
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
main
|