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.
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
@@ -0,0 +1 @@
1
+ cparse.o: cparse.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
@@ -0,0 +1,7 @@
1
+ # $Id$
2
+
3
+ ENV["ARCHFLAGS"] = "-arch #{`uname -p` =~ /powerpc/ ? 'ppc' : 'i386'}"
4
+
5
+ require 'mkmf'
6
+
7
+ create_makefile 'racc/cparse/cparse'
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'corecache'
@@ -0,0 +1,185 @@
1
+ /*
2
+ $Id$
3
+
4
+ Copyright (C) 2005 Minero Aoki
5
+
6
+ This program is free software.
7
+ You can distribute/modify this program under the terms of
8
+ the GNU LGPL, Lesser General Public Licese version 2.1.
9
+ */
10
+
11
+ #include "ruby.h"
12
+
13
+ static VALUE LALRcoreCache;
14
+
15
+ struct item_holder {
16
+ unsigned long hashval;
17
+ VALUE core;
18
+ VALUE state;
19
+ struct item_holder *next;
20
+ };
21
+
22
+ struct lalr_state_cache {
23
+ struct item_holder **bin;
24
+ long size;
25
+ long num;
26
+ };
27
+
28
+ static void
29
+ lalrc_free(struct lalr_state_cache *p)
30
+ {
31
+ struct item_holder *tmp;
32
+ long i;
33
+
34
+ for (i = 0; i < p->size; i++) {
35
+ while (tmp = p->bin[i]) {
36
+ p->bin[i] = tmp->next;
37
+ free(tmp);
38
+ }
39
+ }
40
+ free(p->bin);
41
+ free(p);
42
+ }
43
+
44
+ #define INIT_BIN 256
45
+
46
+ static VALUE
47
+ lalrc_s_new(VALUE self)
48
+ {
49
+ struct lalr_state_cache *cache;
50
+
51
+ cache = ALLOC_N(struct lalr_state_cache, 1);
52
+ cache->bin = ALLOC_N(struct item_holder*, INIT_BIN);
53
+ cache->size = INIT_BIN;
54
+ cache->num = 0;
55
+ return Data_Wrap_Struct(LALRcoreCache, 0, lalrc_free, cache);
56
+ }
57
+
58
+ #define GET_LALRC(self, p) Data_Get_Struct(self, struct lalr_state_cache, p)
59
+
60
+ static void
61
+ lalrc_rehash(struct lalr_state_cache *p)
62
+ {
63
+ struct item_holder *top = 0, *tmp = 0;
64
+ long i;
65
+
66
+ for (i = p->size / 2; i < p->size; i++) {
67
+ p->bin[i] = 0;
68
+ }
69
+ for (i = 0; i < p->size / 2; i++) {
70
+ if (!p->bin[i])
71
+ continue;
72
+
73
+ tmp = p->bin[i];
74
+ while (tmp->next)
75
+ tmp = tmp->next;
76
+ tmp->next = top;
77
+ top = p->bin[i];
78
+ p->bin[i] = 0;
79
+ }
80
+
81
+ while (top) {
82
+ tmp = top;
83
+ top = tmp->next;
84
+ tmp->next = 0;
85
+
86
+ i = tmp->hashval % p->size;
87
+ if (p->bin[i]) {
88
+ tmp->next = p->bin[i];
89
+ p->bin[i] = tmp;
90
+ }
91
+ else {
92
+ p->bin[i] = tmp;
93
+ }
94
+ }
95
+ }
96
+
97
+ static int
98
+ coreeql(VALUE a, VALUE b)
99
+ {
100
+ long i;
101
+
102
+ /* Check_Type(a, T_ARRAY);
103
+ Check_Type(b, T_ARRAY); */
104
+ if (RARRAY(a)->len != RARRAY(b)->len)
105
+ return 0;
106
+ for (i = 0; i < RARRAY(a)->len; i++)
107
+ if (RARRAY(a)->ptr[i] != RARRAY(b)->ptr[i])
108
+ return 0;
109
+
110
+ return 1;
111
+ }
112
+
113
+ static unsigned long
114
+ hashval(VALUE core)
115
+ {
116
+ unsigned long v = 0;
117
+ long i, j;
118
+
119
+ for (i = 0; i < RARRAY(core)->len; i++) {
120
+ v *= RARRAY(core)->ptr[i];
121
+ v ^= RARRAY(core)->ptr[i];
122
+ }
123
+ return v;
124
+ }
125
+
126
+ static VALUE
127
+ lalrc_aref(VALUE self, VALUE core)
128
+ {
129
+ struct lalr_state_cache *p;
130
+ unsigned long v;
131
+ long i;
132
+ struct item_holder *ad;
133
+
134
+ /* Check_Type(core, T_ARRAY); */
135
+ GET_LALRC(self, p);
136
+ v = hashval(core);
137
+ i = v % p->size;
138
+ ad = p->bin[i];
139
+ while (ad) {
140
+ if (ad->hashval == v) {
141
+ if (coreeql(core, ad->core)) {
142
+ return ad->state;
143
+ }
144
+ else {
145
+ printf(".");
146
+ }
147
+ }
148
+ ad = ad->next;
149
+ }
150
+ return Qnil;
151
+ }
152
+
153
+ static VALUE
154
+ lalrc_add_direct(VALUE self, VALUE core, VALUE state)
155
+ {
156
+ struct lalr_state_cache *p;
157
+ struct item_holder *ad;
158
+ long i;
159
+
160
+ GET_LALRC(self, p);
161
+ ad = ALLOC_N(struct item_holder, 1);
162
+ ad->hashval = hashval(core);
163
+ ad->core = core;
164
+ ad->state = state;
165
+
166
+ i = ad->hashval % p->size;
167
+ ad->next = p->bin[i];
168
+ p->bin[i] = ad;
169
+ p->num++;
170
+ if ((p->num / p->size) >= 1) {
171
+ REALLOC_N(p->bin, struct item_holder*, p->size * 2);
172
+ p->size *= 2;
173
+ lalrc_rehash(p);
174
+ }
175
+ return Qnil;
176
+ }
177
+
178
+ void
179
+ Init_corecache(void)
180
+ {
181
+ LALRcoreCache = rb_define_class("LALRcoreCache", rb_cObject);
182
+ rb_define_singleton_method(LALRcoreCache, "new", lalrc_s_new, 0);
183
+ rb_define_method(LALRcoreCache, "[]", lalrc_aref, 1);
184
+ rb_define_method(LALRcoreCache, "[]=", lalrc_add_direct, 2);
185
+ }
@@ -0,0 +1,6 @@
1
+ require 'racc/compat'
2
+ require 'racc/debugflags'
3
+ require 'racc/grammar'
4
+ require 'racc/state'
5
+ require 'racc/exception'
6
+ require 'racc/info'
@@ -0,0 +1,40 @@
1
+ #
2
+ # $Id$
3
+ #
4
+ # Copyright (c) 1999-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of the GNU LGPL, see the file "COPYING".
10
+ #
11
+
12
+ unless Object.method_defined?(:__send)
13
+ class Object
14
+ alias __send __send__
15
+ end
16
+ end
17
+
18
+ unless Object.method_defined?(:__send!)
19
+ class Object
20
+ alias __send! __send__
21
+ end
22
+ end
23
+
24
+ unless String.method_defined?(:to_a)
25
+ class String
26
+ def to_a
27
+ lines.to_a
28
+ end
29
+ end
30
+ end
31
+
32
+ unless Array.method_defined?(:map!)
33
+ class Array
34
+ if Array.method_defined?(:collect!)
35
+ alias map! collect!
36
+ else
37
+ alias map! filter
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ #
2
+ # $Id$
3
+ #
4
+ # Copyright (c) 1999-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of LGPL, see the file "COPYING".
10
+ #
11
+
12
+ module Racc
13
+
14
+ class DebugFlags
15
+ def DebugFlags.parse_option_string(s)
16
+ parse = rule = token = state = la = prec = conf = false
17
+ s.split(//).each do |ch|
18
+ case ch
19
+ when 'p' then parse = true
20
+ when 'r' then rule = true
21
+ when 't' then token = true
22
+ when 's' then state = true
23
+ when 'l' then la = true
24
+ when 'c' then prec = true
25
+ when 'o' then conf = true
26
+ else
27
+ raise "unknown debug flag char: #{ch.inspect}"
28
+ end
29
+ end
30
+ new(parse, rule, token, state, la, prec, conf)
31
+ end
32
+
33
+ def initialize(parse = false, rule = false, token = false, state = false,
34
+ la = false, prec = false, conf = false)
35
+ @parse = parse
36
+ @rule = rule
37
+ @token = token
38
+ @state = state
39
+ @la = la
40
+ @prec = prec
41
+ @any = (parse || rule || token || state || la || prec)
42
+ @status_logging = conf
43
+ end
44
+
45
+ attr_reader :parse
46
+ attr_reader :rule
47
+ attr_reader :token
48
+ attr_reader :state
49
+ attr_reader :la
50
+ attr_reader :prec
51
+
52
+ def any?
53
+ @any
54
+ end
55
+
56
+ attr_reader :status_logging
57
+ end
58
+
59
+ end
@@ -0,0 +1,15 @@
1
+ #
2
+ # $Id$
3
+ #
4
+ # Copyright (c) 1999-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of the GNU LGPL, see the file "COPYING".
10
+ #
11
+
12
+ module Racc
13
+ class Error < StandardError; end
14
+ class CompileError < Error; end
15
+ end
@@ -0,0 +1,1115 @@
1
+ #
2
+ # $Id$
3
+ #
4
+ # Copyright (c) 1999-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of the GNU LGPL, see the file "COPYING".
10
+ #
11
+
12
+ require 'racc/compat'
13
+ require 'racc/iset'
14
+ require 'racc/sourcetext'
15
+ require 'racc/logfilegenerator'
16
+ require 'racc/exception'
17
+ require 'forwardable'
18
+
19
+ module Racc
20
+
21
+ class Grammar
22
+
23
+ def initialize(debug_flags = DebugFlags.new)
24
+ @symboltable = SymbolTable.new
25
+ @debug_symbol = debug_flags.token
26
+ @rules = [] # :: [Rule]
27
+ @start = nil
28
+ @n_expected_srconflicts = nil
29
+ @prec_table = []
30
+ @prec_table_closed = false
31
+ @closed = false
32
+ @states = nil
33
+ end
34
+
35
+ attr_reader :start
36
+ attr_reader :symboltable
37
+ attr_accessor :n_expected_srconflicts
38
+
39
+ def [](x)
40
+ @rules[x]
41
+ end
42
+
43
+ def each_rule(&block)
44
+ @rules.each(&block)
45
+ end
46
+
47
+ alias each each_rule
48
+
49
+ def each_index(&block)
50
+ @rules.each_index(&block)
51
+ end
52
+
53
+ def each_with_index(&block)
54
+ @rules.each_with_index(&block)
55
+ end
56
+
57
+ def size
58
+ @rules.size
59
+ end
60
+
61
+ def to_s
62
+ "<Racc::Grammar>"
63
+ end
64
+
65
+ extend Forwardable
66
+
67
+ def_delegator "@symboltable", :each, :each_symbol
68
+ def_delegator "@symboltable", :each_terminal
69
+ def_delegator "@symboltable", :each_nonterminal
70
+
71
+ def intern(value, dummy = false)
72
+ @symboltable.intern(value, dummy)
73
+ end
74
+
75
+ def symbols
76
+ @symboltable.symbols
77
+ end
78
+
79
+ def nonterminal_base
80
+ @symboltable.nt_base
81
+ end
82
+
83
+ def useless_nonterminal_exist?
84
+ n_useless_nonterminals() != 0
85
+ end
86
+
87
+ def n_useless_nonterminals
88
+ @n_useless_nonterminals ||=
89
+ begin
90
+ n = 0
91
+ @symboltable.each_nonterminal do |sym|
92
+ n += 1 if sym.useless?
93
+ end
94
+ n
95
+ end
96
+ end
97
+
98
+ def useless_rule_exist?
99
+ n_useless_rules() != 0
100
+ end
101
+
102
+ def n_useless_rules
103
+ @n_useless_rules ||=
104
+ begin
105
+ n = 0
106
+ each do |r|
107
+ n += 1 if r.useless?
108
+ end
109
+ n
110
+ end
111
+ end
112
+
113
+ def nfa
114
+ (@states ||= States.new(self)).nfa
115
+ end
116
+
117
+ def dfa
118
+ (@states ||= States.new(self)).dfa
119
+ end
120
+
121
+ alias states dfa
122
+
123
+ def state_transition_table
124
+ states().state_transition_table
125
+ end
126
+
127
+ def parser_class
128
+ states = states() # cache
129
+ if $DEBUG
130
+ srcfilename = caller(1).first.slice(/\A(.*?):/, 1)
131
+ begin
132
+ write_log srcfilename + ".output"
133
+ rescue SystemCallError
134
+ end
135
+ report = lambda {|s| $stderr.puts "racc: #{srcfilename}: #{s}" }
136
+ if states.should_report_srconflict?
137
+ report["#{states.n_srconflicts} shift/reduce conflicts"]
138
+ end
139
+ if states.rrconflict_exist?
140
+ report["#{states.n_rrconflicts} reduce/reduce conflicts"]
141
+ end
142
+ g = states.grammar
143
+ if g.useless_nonterminal_exist?
144
+ report["#{g.n_useless_nonterminals} useless nonterminals"]
145
+ end
146
+ if g.useless_rule_exist?
147
+ report["#{g.n_useless_rules} useless rules"]
148
+ end
149
+ end
150
+ states.state_transition_table.parser_class
151
+ end
152
+
153
+ def write_log(path)
154
+ File.open(path, 'w') {|f|
155
+ LogFileGenerator.new(states()).output f
156
+ }
157
+ end
158
+
159
+ #
160
+ # Grammar Definition Interface
161
+ #
162
+
163
+ def add(rule)
164
+ raise ArgumentError, "rule added after the Grammar closed" if @closed
165
+ @rules.push rule
166
+ end
167
+
168
+ def added?(sym)
169
+ @rules.detect {|r| r.target == sym }
170
+ end
171
+
172
+ def start_symbol=(s)
173
+ raise CompileError, "start symbol set twice'" if @start
174
+ @start = s
175
+ end
176
+
177
+ def declare_precedence(assoc, syms)
178
+ raise CompileError, "precedence table defined twice" if @prec_table_closed
179
+ @prec_table.push [assoc, syms]
180
+ end
181
+
182
+ def end_precedence_declaration(reverse)
183
+ @prec_table_closed = true
184
+ return if @prec_table.empty?
185
+ table = reverse ? @prec_table.reverse : @prec_table
186
+ table.each_with_index do |(assoc, syms), idx|
187
+ syms.each do |sym|
188
+ sym.assoc = assoc
189
+ sym.precedence = idx
190
+ end
191
+ end
192
+ end
193
+
194
+ #
195
+ # Dynamic Generation Interface
196
+ #
197
+
198
+ def Grammar.define(&block)
199
+ env = DefinitionEnv.new
200
+ env.instance_eval(&block)
201
+ env.grammar
202
+ end
203
+
204
+ class DefinitionEnv
205
+ def initialize
206
+ @grammar = Grammar.new
207
+ @seqs = Hash.new(0)
208
+ @delayed = []
209
+ end
210
+
211
+ def grammar
212
+ flush_delayed
213
+ @grammar.each do |rule|
214
+ if rule.specified_prec
215
+ rule.specified_prec = @grammar.intern(rule.specified_prec)
216
+ end
217
+ end
218
+ @grammar.init
219
+ @grammar
220
+ end
221
+
222
+ def precedence_table(&block)
223
+ env = PrecedenceDefinitionEnv.new(@grammar)
224
+ env.instance_eval(&block)
225
+ @grammar.end_precedence_declaration env.reverse
226
+ end
227
+
228
+ def method_missing(mid, *args, &block)
229
+ unless mid.to_s[-1,1] == '='
230
+ super # raises NoMethodError
231
+ end
232
+ target = @grammar.intern(mid.to_s.chop.intern)
233
+ unless args.size == 1
234
+ raise ArgumentError, "too many arguments for #{mid} (#{args.size} for 1)"
235
+ end
236
+ _add target, args.first
237
+ end
238
+
239
+ def _add(target, x)
240
+ case x
241
+ when Sym
242
+ @delayed.each do |rule|
243
+ rule.replace x, target if rule.target == x
244
+ end
245
+ @grammar.symboltable.delete x
246
+ else
247
+ x.each_rule do |r|
248
+ r.target = target
249
+ @grammar.add r
250
+ end
251
+ end
252
+ flush_delayed
253
+ end
254
+
255
+ def _delayed_add(rule)
256
+ @delayed.push rule
257
+ end
258
+
259
+ def _added?(sym)
260
+ @grammar.added?(sym) or @delayed.detect {|r| r.target == sym }
261
+ end
262
+
263
+ def flush_delayed
264
+ return if @delayed.empty?
265
+ @delayed.each do |rule|
266
+ @grammar.add rule
267
+ end
268
+ @delayed.clear
269
+ end
270
+
271
+ def seq(*list, &block)
272
+ Rule.new(nil, list.map {|x| _intern(x) }, UserAction.proc(block))
273
+ end
274
+
275
+ def null(&block)
276
+ seq(&block)
277
+ end
278
+
279
+ def action(&block)
280
+ id = "@#{@seqs["action"] += 1}".intern
281
+ _delayed_add Rule.new(@grammar.intern(id), [], UserAction.proc(block))
282
+ id
283
+ end
284
+
285
+ alias _ action
286
+
287
+ def option(sym, default = nil, &block)
288
+ _defmetasyntax("option", _intern(sym), block) {|target|
289
+ seq() { default } | seq(sym)
290
+ }
291
+ end
292
+
293
+ def many(sym, &block)
294
+ _defmetasyntax("many", _intern(sym), block) {|target|
295
+ seq() { [] }\
296
+ | seq(target, sym) {|list, x| list.push x; list }
297
+ }
298
+ end
299
+
300
+ def many1(sym, &block)
301
+ _defmetasyntax("many1", _intern(sym), block) {|target|
302
+ seq(sym) {|x| [x] }\
303
+ | seq(target, sym) {|list, x| list.push x; list }
304
+ }
305
+ end
306
+
307
+ def separated_by(sep, sym, &block)
308
+ option(separated_by1(sep, sym), [], &block)
309
+ end
310
+
311
+ def separated_by1(sep, sym, &block)
312
+ _defmetasyntax("separated_by1", _intern(sym), block) {|target|
313
+ seq(sym) {|x| [x] }\
314
+ | seq(target, sep, sym) {|list, _, x| list.push x; list }
315
+ }
316
+ end
317
+
318
+ def _intern(x)
319
+ case x
320
+ when Symbol, String
321
+ @grammar.intern(x)
322
+ when Racc::Sym
323
+ x
324
+ else
325
+ raise TypeError, "wrong type #{x.class} (expected Symbol/String/Racc::Sym)"
326
+ end
327
+ end
328
+
329
+ private
330
+
331
+ def _defmetasyntax(type, id, action, &block)
332
+ if action
333
+ idbase = "#{type}@#{id}-#{@seqs[type] += 1}"
334
+ target = _wrap(idbase, "#{idbase}-core", action)
335
+ _regist("#{idbase}-core", &block)
336
+ else
337
+ target = _regist("#{type}@#{id}", &block)
338
+ end
339
+ @grammar.intern(target)
340
+ end
341
+
342
+ def _regist(target_name)
343
+ target = target_name.intern
344
+ unless _added?(@grammar.intern(target))
345
+ yield(target).each_rule do |rule|
346
+ rule.target = @grammar.intern(target)
347
+ _delayed_add rule
348
+ end
349
+ end
350
+ target
351
+ end
352
+
353
+ def _wrap(target_name, sym, block)
354
+ target = target_name.intern
355
+ _delayed_add Rule.new(@grammar.intern(target),
356
+ [@grammar.intern(sym.intern)],
357
+ UserAction.proc(block))
358
+ target
359
+ end
360
+ end
361
+
362
+ class PrecedenceDefinitionEnv
363
+ def initialize(g)
364
+ @grammar = g
365
+ @prechigh_seen = false
366
+ @preclow_seen = false
367
+ @reverse = false
368
+ end
369
+
370
+ attr_reader :reverse
371
+
372
+ def higher
373
+ if @prechigh_seen
374
+ raise CompileError, "prechigh used twice"
375
+ end
376
+ @prechigh_seen = true
377
+ end
378
+
379
+ def lower
380
+ if @preclow_seen
381
+ raise CompileError, "preclow used twice"
382
+ end
383
+ if @prechigh_seen
384
+ @reverse = true
385
+ end
386
+ @preclow_seen = true
387
+ end
388
+
389
+ def left(*syms)
390
+ @grammar.declare_precedence :Left, syms.map {|s| @grammar.intern(s) }
391
+ end
392
+
393
+ def right(*syms)
394
+ @grammar.declare_precedence :Right, syms.map {|s| @grammar.intern(s) }
395
+ end
396
+
397
+ def nonassoc(*syms)
398
+ @grammar.declare_precedence :Nonassoc, syms.map {|s| @grammar.intern(s)}
399
+ end
400
+ end
401
+
402
+ #
403
+ # Computation
404
+ #
405
+
406
+ def init
407
+ return if @closed
408
+ @closed = true
409
+ @start ||= @rules.map {|r| r.target }.detect {|sym| not sym.dummy? }
410
+ raise CompileError, 'no rule in input' if @rules.empty?
411
+ add_start_rule
412
+ @rules.freeze
413
+ fix_ident
414
+ compute_hash
415
+ compute_heads
416
+ determine_terminals
417
+ compute_nullable_0
418
+ @symboltable.fix
419
+ compute_locate
420
+ @symboltable.each_nonterminal {|t| compute_expand t }
421
+ compute_nullable
422
+ compute_useless
423
+ end
424
+
425
+ private
426
+
427
+ def add_start_rule
428
+ r = Rule.new(@symboltable.dummy,
429
+ [@start, @symboltable.anchor, @symboltable.anchor],
430
+ UserAction.empty)
431
+ r.ident = 0
432
+ r.hash = 0
433
+ r.precedence = nil
434
+ @rules.unshift r
435
+ end
436
+
437
+ # Rule#ident
438
+ # LocationPointer#ident
439
+ def fix_ident
440
+ @rules.each_with_index do |rule, idx|
441
+ rule.ident = idx
442
+ end
443
+ end
444
+
445
+ # Rule#hash
446
+ def compute_hash
447
+ hash = 4 # size of dummy rule
448
+ @rules.each do |rule|
449
+ rule.hash = hash
450
+ hash += (rule.size + 1)
451
+ end
452
+ end
453
+
454
+ # Sym#heads
455
+ def compute_heads
456
+ @rules.each do |rule|
457
+ rule.target.heads.push rule.ptrs[0]
458
+ end
459
+ end
460
+
461
+ # Sym#terminal?
462
+ def determine_terminals
463
+ @symboltable.each do |s|
464
+ s.term = s.heads.empty?
465
+ end
466
+ end
467
+
468
+ # Sym#self_null?
469
+ def compute_nullable_0
470
+ @symboltable.each do |s|
471
+ if s.terminal?
472
+ s.snull = false
473
+ else
474
+ s.snull = s.heads.any? {|loc| loc.reduce? }
475
+ end
476
+ end
477
+ end
478
+
479
+ # Sym#locate
480
+ def compute_locate
481
+ @rules.each do |rule|
482
+ t = nil
483
+ rule.ptrs.each do |ptr|
484
+ unless ptr.reduce?
485
+ tok = ptr.dereference
486
+ tok.locate.push ptr
487
+ t = tok if tok.terminal?
488
+ end
489
+ end
490
+ rule.precedence = t
491
+ end
492
+ end
493
+
494
+ # Sym#expand
495
+ def compute_expand(t)
496
+ puts "expand> #{t.to_s}" if @debug_symbol
497
+ t.expand = _compute_expand(t, ISet.new, [])
498
+ puts "expand< #{t.to_s}: #{t.expand.to_s}" if @debug_symbol
499
+ end
500
+
501
+ def _compute_expand(t, set, lock)
502
+ if tmp = t.expand
503
+ set.update tmp
504
+ return set
505
+ end
506
+ tok = h = nil
507
+ set.update_a t.heads
508
+ t.heads.each do |ptr|
509
+ tok = ptr.dereference
510
+ if tok and tok.nonterminal?
511
+ unless lock[tok.ident]
512
+ lock[tok.ident] = true
513
+ _compute_expand tok, set, lock
514
+ end
515
+ end
516
+ end
517
+ set
518
+ end
519
+
520
+ # Sym#nullable?, Rule#nullable?
521
+ def compute_nullable
522
+ @rules.each {|r| r.null = false }
523
+ @symboltable.each {|t| t.null = false }
524
+ r = @rules.dup
525
+ s = @symboltable.nonterminals
526
+ begin
527
+ rs = r.size
528
+ ss = s.size
529
+ check_rules_nullable r
530
+ check_symbols_nullable s
531
+ end until rs == r.size and ss == s.size
532
+ end
533
+
534
+ def check_rules_nullable(rules)
535
+ rules.delete_if do |rule|
536
+ rule.null = true
537
+ rule.symbols.each do |t|
538
+ unless t.nullable?
539
+ rule.null = false
540
+ break
541
+ end
542
+ end
543
+ rule.nullable?
544
+ end
545
+ end
546
+
547
+ def check_symbols_nullable(symbols)
548
+ symbols.delete_if do |sym|
549
+ sym.heads.each do |ptr|
550
+ if ptr.rule.nullable?
551
+ sym.null = true
552
+ break
553
+ end
554
+ end
555
+ sym.nullable?
556
+ end
557
+ end
558
+
559
+ # Sym#useless?, Rule#useless?
560
+ # FIXME: what means "useless"?
561
+ def compute_useless
562
+ @symboltable.each_terminal {|sym| sym.useless = false }
563
+ @symboltable.each_nonterminal {|sym| sym.useless = true }
564
+ @rules.each {|rule| rule.useless = true }
565
+ r = @rules.dup
566
+ s = @symboltable.nonterminals
567
+ begin
568
+ rs = r.size
569
+ ss = s.size
570
+ check_rules_useless r
571
+ check_symbols_useless s
572
+ end until r.size == rs and s.size == ss
573
+ end
574
+
575
+ def check_rules_useless(rules)
576
+ rules.delete_if do |rule|
577
+ rule.useless = false
578
+ rule.symbols.each do |sym|
579
+ if sym.useless?
580
+ rule.useless = true
581
+ break
582
+ end
583
+ end
584
+ not rule.useless?
585
+ end
586
+ end
587
+
588
+ def check_symbols_useless(s)
589
+ s.delete_if do |t|
590
+ t.heads.each do |ptr|
591
+ unless ptr.rule.useless?
592
+ t.useless = false
593
+ break
594
+ end
595
+ end
596
+ not t.useless?
597
+ end
598
+ end
599
+
600
+ end # class Grammar
601
+
602
+
603
+ class Rule
604
+
605
+ def initialize(target, syms, act)
606
+ @target = target
607
+ @symbols = syms
608
+ @action = act
609
+ @alternatives = []
610
+
611
+ @ident = nil
612
+ @hash = nil
613
+ @ptrs = nil
614
+ @precedence = nil
615
+ @specified_prec = nil
616
+ @null = nil
617
+ @useless = nil
618
+ end
619
+
620
+ attr_accessor :target
621
+ attr_reader :symbols
622
+ attr_reader :action
623
+
624
+ def |(x)
625
+ @alternatives.push x.rule
626
+ self
627
+ end
628
+
629
+ def rule
630
+ self
631
+ end
632
+
633
+ def each_rule(&block)
634
+ yield self
635
+ @alternatives.each(&block)
636
+ end
637
+
638
+ attr_accessor :ident
639
+
640
+ attr_reader :hash
641
+ attr_reader :ptrs
642
+
643
+ def hash=(n)
644
+ @hash = n
645
+ ptrs = []
646
+ @symbols.each_with_index do |sym, idx|
647
+ ptrs.push LocationPointer.new(self, idx, sym)
648
+ end
649
+ ptrs.push LocationPointer.new(self, @symbols.size, nil)
650
+ @ptrs = ptrs
651
+ end
652
+
653
+ def precedence
654
+ @specified_prec || @precedence
655
+ end
656
+
657
+ def precedence=(sym)
658
+ @precedence ||= sym
659
+ end
660
+
661
+ def prec(sym, &block)
662
+ @specified_prec = sym
663
+ if block
664
+ unless @action.empty?
665
+ raise CompileError, 'both of rule action block and prec block given'
666
+ end
667
+ @action = UserAction.proc(block)
668
+ end
669
+ self
670
+ end
671
+
672
+ attr_accessor :specified_prec
673
+
674
+ def nullable?() @null end
675
+ def null=(n) @null = n end
676
+
677
+ def useless?() @useless end
678
+ def useless=(u) @useless = u end
679
+
680
+ def inspect
681
+ "#<Racc::Rule id=#{@ident} (#{@target})>"
682
+ end
683
+
684
+ def ==(other)
685
+ other.kind_of?(Rule) and @ident == other.ident
686
+ end
687
+
688
+ def [](idx)
689
+ @symbols[idx]
690
+ end
691
+
692
+ def size
693
+ @symbols.size
694
+ end
695
+
696
+ def empty?
697
+ @symbols.empty?
698
+ end
699
+
700
+ def to_s
701
+ "#<rule#{@ident}>"
702
+ end
703
+
704
+ def accept?
705
+ if tok = @symbols[-1]
706
+ tok.anchor?
707
+ else
708
+ false
709
+ end
710
+ end
711
+
712
+ def each(&block)
713
+ @symbols.each(&block)
714
+ end
715
+
716
+ def replace(src, dest)
717
+ @target = dest
718
+ @symbols = @symbols.map {|s| s == src ? dest : s }
719
+ end
720
+
721
+ end # class Rule
722
+
723
+
724
+ class UserAction
725
+
726
+ def UserAction.source_text(src)
727
+ new(src, nil)
728
+ end
729
+
730
+ def UserAction.proc(pr = nil, &block)
731
+ if pr and block
732
+ raise ArgumentError, "both of argument and block given"
733
+ end
734
+ new(nil, pr || block)
735
+ end
736
+
737
+ def UserAction.empty
738
+ new(nil, nil)
739
+ end
740
+
741
+ private_class_method :new
742
+
743
+ def initialize(src, proc)
744
+ @source = src
745
+ @proc = proc
746
+ end
747
+
748
+ attr_reader :source
749
+ attr_reader :proc
750
+
751
+ def source?
752
+ not @proc
753
+ end
754
+
755
+ def proc?
756
+ not @source
757
+ end
758
+
759
+ def empty?
760
+ not @proc and not @source
761
+ end
762
+
763
+ def name
764
+ "{action type=#{@source || @proc || 'nil'}}"
765
+ end
766
+
767
+ alias inspect name
768
+
769
+ end
770
+
771
+
772
+ class OrMark
773
+ def initialize(lineno)
774
+ @lineno = lineno
775
+ end
776
+
777
+ def name
778
+ '|'
779
+ end
780
+
781
+ alias inspect name
782
+
783
+ attr_reader :lineno
784
+ end
785
+
786
+
787
+ class Prec
788
+ def initialize(symbol, lineno)
789
+ @symbol = symbol
790
+ @lineno = lineno
791
+ end
792
+
793
+ def name
794
+ "=#{@symbol}"
795
+ end
796
+
797
+ alias inspect name
798
+
799
+ attr_reader :symbol
800
+ attr_reader :lineno
801
+ end
802
+
803
+
804
+ #
805
+ # A set of rule and position in it's RHS.
806
+ # Note that the number of pointers is more than rule's RHS array,
807
+ # because pointer points right edge of the final symbol when reducing.
808
+ #
809
+ class LocationPointer
810
+
811
+ def initialize(rule, i, sym)
812
+ @rule = rule
813
+ @index = i
814
+ @symbol = sym
815
+ @ident = @rule.hash + i
816
+ @reduce = sym.nil?
817
+ end
818
+
819
+ attr_reader :rule
820
+ attr_reader :index
821
+ attr_reader :symbol
822
+
823
+ alias dereference symbol
824
+
825
+ attr_reader :ident
826
+ alias hash ident
827
+ attr_reader :reduce
828
+ alias reduce? reduce
829
+
830
+ def to_s
831
+ sprintf('(%d,%d %s)',
832
+ @rule.ident, @index, (reduce?() ? '#' : @symbol.to_s))
833
+ end
834
+
835
+ alias inspect to_s
836
+
837
+ def eql?(ot)
838
+ @hash == ot.hash
839
+ end
840
+
841
+ alias == eql?
842
+
843
+ def head?
844
+ @index == 0
845
+ end
846
+
847
+ def next
848
+ @rule.ptrs[@index + 1] or ptr_bug!
849
+ end
850
+
851
+ alias increment next
852
+
853
+ def before(len)
854
+ @rule.ptrs[@index - len] or ptr_bug!
855
+ end
856
+
857
+ private
858
+
859
+ def ptr_bug!
860
+ raise "racc: fatal: pointer not exist: self: #{to_s}"
861
+ end
862
+
863
+ end # class LocationPointer
864
+
865
+
866
+ class SymbolTable
867
+
868
+ include Enumerable
869
+
870
+ def initialize
871
+ @symbols = [] # :: [Racc::Sym]
872
+ @cache = {} # :: {(String|Symbol) => Racc::Sym}
873
+ @dummy = intern(:$start, true)
874
+ @anchor = intern(false, true) # Symbol ID = 0
875
+ @error = intern(:error, false) # Symbol ID = 1
876
+ end
877
+
878
+ attr_reader :dummy
879
+ attr_reader :anchor
880
+ attr_reader :error
881
+
882
+ def [](id)
883
+ @symbols[id]
884
+ end
885
+
886
+ def intern(val, dummy = false)
887
+ @cache[val] ||=
888
+ begin
889
+ sym = Sym.new(val, dummy)
890
+ @symbols.push sym
891
+ sym
892
+ end
893
+ end
894
+
895
+ attr_reader :symbols
896
+ alias to_a symbols
897
+
898
+ def delete(sym)
899
+ @symbols.delete sym
900
+ @cache.delete sym.value
901
+ end
902
+
903
+ attr_reader :nt_base
904
+
905
+ def nt_max
906
+ @symbols.size
907
+ end
908
+
909
+ def each(&block)
910
+ @symbols.each(&block)
911
+ end
912
+
913
+ def terminals(&block)
914
+ @symbols[0, @nt_base]
915
+ end
916
+
917
+ def each_terminal(&block)
918
+ @terms.each(&block)
919
+ end
920
+
921
+ def nonterminals
922
+ @symbols[@nt_base, @symbols.size - @nt_base]
923
+ end
924
+
925
+ def each_nonterminal(&block)
926
+ @nterms.each(&block)
927
+ end
928
+
929
+ def fix
930
+ terms, nterms = @symbols.partition {|s| s.terminal? }
931
+ @symbols = terms + nterms
932
+ @terms = terms
933
+ @nterms = nterms
934
+ @nt_base = terms.size
935
+ fix_ident
936
+ check_terminals
937
+ end
938
+
939
+ private
940
+
941
+ def fix_ident
942
+ @symbols.each_with_index do |t, i|
943
+ t.ident = i
944
+ end
945
+ end
946
+
947
+ def check_terminals
948
+ return unless @symbols.any? {|s| s.should_terminal? }
949
+ @anchor.should_terminal
950
+ @error.should_terminal
951
+ each_terminal do |t|
952
+ t.should_terminal if t.string_symbol?
953
+ end
954
+ each do |s|
955
+ s.should_terminal if s.assoc
956
+ end
957
+ terminals().reject {|t| t.should_terminal? }.each do |t|
958
+ raise CompileError, "terminal #{t} not declared as terminal"
959
+ end
960
+ nonterminals().select {|n| n.should_terminal? }.each do |n|
961
+ raise CompileError, "symbol #{n} declared as terminal but is not terminal"
962
+ end
963
+ end
964
+
965
+ end # class SymbolTable
966
+
967
+
968
+ # Stands terminal and nonterminal symbols.
969
+ class Sym
970
+
971
+ def initialize(value, dummyp)
972
+ @ident = nil
973
+ @value = value
974
+ @dummyp = dummyp
975
+
976
+ @term = nil
977
+ @nterm = nil
978
+ @should_terminal = false
979
+ @precedence = nil
980
+ case value
981
+ when Symbol
982
+ @to_s = value.to_s
983
+ @serialized = value.inspect
984
+ @string = false
985
+ when String
986
+ @to_s = value.inspect
987
+ @serialized = value.dump
988
+ @string = true
989
+ when false
990
+ @to_s = '$end'
991
+ @serialized = 'false'
992
+ @string = false
993
+ when ErrorSymbolValue
994
+ @to_s = 'error'
995
+ @serialized = 'Object.new'
996
+ @string = false
997
+ else
998
+ raise ArgumentError, "unknown symbol value: #{value.class}"
999
+ end
1000
+
1001
+ @heads = []
1002
+ @locate = []
1003
+ @snull = nil
1004
+ @null = nil
1005
+ @expand = nil
1006
+ @useless = nil
1007
+ end
1008
+
1009
+ class << self
1010
+ def once_writer(nm)
1011
+ nm = nm.id2name
1012
+ module_eval(<<-EOS)
1013
+ def #{nm}=(v)
1014
+ raise 'racc: fatal: @#{nm} != nil' unless @#{nm}.nil?
1015
+ @#{nm} = v
1016
+ end
1017
+ EOS
1018
+ end
1019
+ end
1020
+
1021
+ once_writer :ident
1022
+ attr_reader :ident
1023
+
1024
+ alias hash ident
1025
+
1026
+ attr_reader :value
1027
+
1028
+ def dummy?
1029
+ @dummyp
1030
+ end
1031
+
1032
+ def terminal?
1033
+ @term
1034
+ end
1035
+
1036
+ def nonterminal?
1037
+ @nterm
1038
+ end
1039
+
1040
+ def term=(t)
1041
+ raise 'racc: fatal: term= called twice' unless @term.nil?
1042
+ @term = t
1043
+ @nterm = !t
1044
+ end
1045
+
1046
+ def should_terminal
1047
+ @should_terminal = true
1048
+ end
1049
+
1050
+ def should_terminal?
1051
+ @should_terminal
1052
+ end
1053
+
1054
+ def string_symbol?
1055
+ @string
1056
+ end
1057
+
1058
+ def serialize
1059
+ @serialized
1060
+ end
1061
+
1062
+ attr_writer :serialized
1063
+
1064
+ attr_accessor :precedence
1065
+ attr_accessor :assoc
1066
+
1067
+ def to_s
1068
+ @to_s.dup
1069
+ end
1070
+
1071
+ alias inspect to_s
1072
+
1073
+ def |(x)
1074
+ rule() | x.rule
1075
+ end
1076
+
1077
+ def rule
1078
+ Rule.new(nil, [self], UserAction.empty)
1079
+ end
1080
+
1081
+ #
1082
+ # cache
1083
+ #
1084
+
1085
+ attr_reader :heads
1086
+ attr_reader :locate
1087
+
1088
+ def self_null?
1089
+ @snull
1090
+ end
1091
+
1092
+ once_writer :snull
1093
+
1094
+ def nullable?
1095
+ @null
1096
+ end
1097
+
1098
+ def null=(n)
1099
+ @null = n
1100
+ end
1101
+
1102
+ attr_reader :expand
1103
+ once_writer :expand
1104
+
1105
+ def useless?
1106
+ @useless
1107
+ end
1108
+
1109
+ def useless=(f)
1110
+ @useless = f
1111
+ end
1112
+
1113
+ end # class Sym
1114
+
1115
+ end # module Racc