racc 1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitattributes +2 -0
  2. data/.gitignore +7 -0
  3. data/COPYING +515 -0
  4. data/ChangeLog +846 -0
  5. data/DEPENDS +4 -0
  6. data/README.en.rdoc +86 -0
  7. data/README.ja.rdoc +96 -0
  8. data/Rakefile +15 -0
  9. data/TODO +5 -0
  10. data/bin/racc +308 -0
  11. data/bin/racc2y +195 -0
  12. data/bin/y2racc +339 -0
  13. data/doc/en/NEWS.en.rdoc +282 -0
  14. data/doc/en/command.en.html +78 -0
  15. data/doc/en/debug.en.rdoc +20 -0
  16. data/doc/en/grammar.en.rdoc +230 -0
  17. data/doc/en/index.en.html +10 -0
  18. data/doc/en/parser.en.rdoc +74 -0
  19. data/doc/en/usage.en.html +92 -0
  20. data/doc/ja/NEWS.ja.rdoc +307 -0
  21. data/doc/ja/command.ja.html +94 -0
  22. data/doc/ja/debug.ja.rdoc +36 -0
  23. data/doc/ja/grammar.ja.rdoc +348 -0
  24. data/doc/ja/index.ja.html +10 -0
  25. data/doc/ja/parser.ja.rdoc +125 -0
  26. data/doc/ja/usage.ja.html +414 -0
  27. data/ext/racc/cparse/MANIFEST +4 -0
  28. data/ext/racc/cparse/cparse.c +824 -0
  29. data/ext/racc/cparse/depend +1 -0
  30. data/ext/racc/cparse/extconf.rb +7 -0
  31. data/fastcache/extconf.rb +2 -0
  32. data/fastcache/fastcache.c +185 -0
  33. data/lib/racc.rb +6 -0
  34. data/lib/racc/compat.rb +40 -0
  35. data/lib/racc/debugflags.rb +59 -0
  36. data/lib/racc/exception.rb +15 -0
  37. data/lib/racc/grammar.rb +1115 -0
  38. data/lib/racc/grammarfileparser.rb +559 -0
  39. data/lib/racc/info.rb +16 -0
  40. data/lib/racc/iset.rb +91 -0
  41. data/lib/racc/logfilegenerator.rb +214 -0
  42. data/lib/racc/parser.rb +439 -0
  43. data/lib/racc/parserfilegenerator.rb +511 -0
  44. data/lib/racc/pre-setup +13 -0
  45. data/lib/racc/sourcetext.rb +34 -0
  46. data/lib/racc/state.rb +971 -0
  47. data/lib/racc/statetransitiontable.rb +316 -0
  48. data/lib/racc/static.rb +5 -0
  49. data/misc/dist.sh +31 -0
  50. data/sample/array.y +67 -0
  51. data/sample/array2.y +59 -0
  52. data/sample/calc-ja.y +66 -0
  53. data/sample/calc.y +65 -0
  54. data/sample/conflict.y +15 -0
  55. data/sample/hash.y +60 -0
  56. data/sample/lalr.y +17 -0
  57. data/sample/lists.y +57 -0
  58. data/sample/syntax.y +46 -0
  59. data/sample/yyerr.y +46 -0
  60. data/setup.rb +1587 -0
  61. data/tasks/doc.rb +12 -0
  62. data/tasks/email.rb +55 -0
  63. data/tasks/file.rb +37 -0
  64. data/tasks/gem.rb +37 -0
  65. data/tasks/test.rb +16 -0
  66. data/test/assets/chk.y +126 -0
  67. data/test/assets/conf.y +16 -0
  68. data/test/assets/digraph.y +29 -0
  69. data/test/assets/echk.y +118 -0
  70. data/test/assets/err.y +60 -0
  71. data/test/assets/expect.y +7 -0
  72. data/test/assets/firstline.y +4 -0
  73. data/test/assets/ichk.y +102 -0
  74. data/test/assets/intp.y +546 -0
  75. data/test/assets/mailp.y +437 -0
  76. data/test/assets/newsyn.y +25 -0
  77. data/test/assets/noend.y +4 -0
  78. data/test/assets/nonass.y +41 -0
  79. data/test/assets/normal.y +27 -0
  80. data/test/assets/norule.y +4 -0
  81. data/test/assets/nullbug1.y +25 -0
  82. data/test/assets/nullbug2.y +15 -0
  83. data/test/assets/opt.y +123 -0
  84. data/test/assets/percent.y +35 -0
  85. data/test/assets/recv.y +97 -0
  86. data/test/assets/rrconf.y +14 -0
  87. data/test/assets/scan.y +72 -0
  88. data/test/assets/syntax.y +50 -0
  89. data/test/assets/unterm.y +5 -0
  90. data/test/assets/useless.y +12 -0
  91. data/test/assets/yyerr.y +46 -0
  92. data/test/bench.y +36 -0
  93. data/test/helper.rb +88 -0
  94. data/test/infini.y +8 -0
  95. data/test/scandata/brace +7 -0
  96. data/test/scandata/gvar +1 -0
  97. data/test/scandata/normal +4 -0
  98. data/test/scandata/percent +18 -0
  99. data/test/scandata/slash +10 -0
  100. data/test/src.intp +34 -0
  101. data/test/start.y +20 -0
  102. data/test/test_chk_y.rb +51 -0
  103. data/test/test_grammar_file_parser.rb +15 -0
  104. data/test/test_racc_command.rb +155 -0
  105. data/test/test_scan_y.rb +51 -0
  106. data/test/testscanner.rb +51 -0
  107. data/web/racc.en.rhtml +42 -0
  108. data/web/racc.ja.rhtml +51 -0
  109. metadata +166 -0
data/DEPENDS ADDED
@@ -0,0 +1,4 @@
1
+ racc: raccruntime
2
+ raccruntime:
3
+ y2racc: strscan
4
+ racc2y: racc
@@ -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
@@ -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
+
@@ -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
@@ -0,0 +1,5 @@
1
+ * check 'error' token handling.
2
+ * interactive transition table monitor.
3
+ * support backtracking.
4
+ * output Ruby extention library?
5
+ * LL(k)? (But it should not be called Racc)
@@ -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