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
@@ -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