depager 0.2.3 → 0.3.0.b20250423

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 (106) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +44 -0
  3. data/.simplecov +5 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE.gpl +339 -0
  6. data/Manifest.txt +73 -0
  7. data/README.en +7 -21
  8. data/README.ja +19 -99
  9. data/Rakefile +31 -0
  10. data/bin/depager +7 -45
  11. data/examples/action_pl0d/pl0d.action.dr +421 -0
  12. data/examples/action_pl0d/test.pl0ds +48 -0
  13. data/examples/c89/c89.dr +493 -496
  14. data/examples/c89/test.c89 +10 -10
  15. data/examples/extension/astdf.rb +9 -0
  16. data/examples/extension/atree.dr +55 -0
  17. data/examples/{sample_calc → extension}/calc.atree.dr +42 -43
  18. data/examples/{sample_calc/calc.action.dr → extension/calc.simple_action.dr} +33 -33
  19. data/examples/extension/paction.dr +16 -15
  20. data/examples/extension/pactiontest.dr +14 -14
  21. data/examples/extension/simple_action.rb +46 -0
  22. data/examples/pl0d/pl0ds.dr +337 -334
  23. data/examples/pl0d/test.pl0ds +33 -33
  24. data/examples/rie_calc/calc.rie.dr +57 -0
  25. data/examples/rie_calc/test.calc +4 -0
  26. data/examples/rie_dcuse/dcuse.rie.dr +71 -0
  27. data/examples/rie_dcuse/test.dcuse +1 -0
  28. data/examples/rie_pl0/orig_ex/exerrdg.pl0 +44 -0
  29. data/examples/rie_pl0/orig_ex/exerrm.pl0 +19 -0
  30. data/examples/rie_pl0/orig_ex/exerrmre.pl0 +20 -0
  31. data/examples/rie_pl0/orig_ex/exerrtok.pl0 +18 -0
  32. data/examples/rie_pl0/orig_ex/exmdg.pl0 +40 -0
  33. data/examples/rie_pl0/orig_ex/exmdgwwl.pl0 +43 -0
  34. data/examples/rie_pl0/orig_ex/exmrw.pl0 +22 -0
  35. data/examples/rie_pl0/orig_ex/exmwwl.pl0 +18 -0
  36. data/examples/rie_pl0/orig_ex/exnorw.pl0 +17 -0
  37. data/examples/rie_pl0/pl0.rie.dr +450 -0
  38. data/examples/rie_pl0/test.pl0 +10 -0
  39. data/examples/slex_test/divreg.slex.dr +29 -29
  40. data/examples/slex_test/ljoin.slex.dr +36 -36
  41. data/examples/slex_test/test.divreg +1 -1
  42. data/examples/slex_test/test.ljoin +3 -3
  43. data/examples/{sample_calc/calc.nvaction.dr → tiny_calc/calc.action.dr} +33 -33
  44. data/examples/{sample_calc → tiny_calc}/calc.ast.action.dr +76 -66
  45. data/examples/{sample_calc → tiny_calc}/calc.ast.dr +67 -55
  46. data/examples/tiny_calc/calc.cst.dr +50 -0
  47. data/examples/{sample_calc → tiny_calc}/calc.dr +43 -43
  48. data/examples/{sample_calc → tiny_calc}/calc.lex.dr +29 -29
  49. data/examples/{sample_calc/calc_prec.nvaction.dr → tiny_calc/calc_prec.action.dr} +31 -31
  50. data/lib/depager/cli.rb +44 -0
  51. data/lib/depager/grammar.rb +253 -291
  52. data/lib/depager/lr.rb +589 -579
  53. data/lib/depager/parser.rb +269 -277
  54. data/lib/depager/plugins/_rie_debug.rb +63 -0
  55. data/lib/depager/plugins/action.rb +47 -0
  56. data/lib/depager/plugins/ast.dr +367 -0
  57. data/lib/depager/plugins/ast.rb +1329 -0
  58. data/lib/depager/{ruby/plugins → plugins}/cst.dr +174 -180
  59. data/lib/depager/plugins/cst.rb +591 -0
  60. data/lib/depager/{ruby/plugins → plugins}/lex.dr +85 -89
  61. data/lib/depager/plugins/lex.rb +313 -0
  62. data/lib/depager/plugins/rie.dr +725 -0
  63. data/lib/depager/plugins/rie.rb +1614 -0
  64. data/lib/depager/{ruby/plugins → plugins}/slex.dr +201 -200
  65. data/lib/depager/plugins/slex.rb +769 -0
  66. data/lib/depager/plugins/srp.rb +46 -0
  67. data/lib/depager/ruby/templates/extension_lalr_master.erb +40 -51
  68. data/lib/depager/ruby/templates/extension_lalr_slave.erb +113 -107
  69. data/lib/depager/ruby/templates/single_lalr_parser.erb +124 -117
  70. data/lib/depager/utils.rb +158 -318
  71. data/lib/depager/version.rb +3 -3
  72. data/lib/depager.rb +572 -670
  73. metadata +77 -80
  74. data/ChangeLog +0 -16
  75. data/data/depager/pre-setup.rb +0 -3
  76. data/examples/c89/c89.tab.rb +0 -7127
  77. data/examples/pl0d/pl0ds.tab.rb +0 -2698
  78. data/examples/sample_calc/calc.action.tab.rb +0 -457
  79. data/examples/sample_calc/calc.ast.action.tab.rb +0 -749
  80. data/examples/sample_calc/calc.ast.tab.rb +0 -665
  81. data/examples/sample_calc/calc.astdf.dr +0 -54
  82. data/examples/sample_calc/calc.astdf.tab.rb +0 -672
  83. data/examples/sample_calc/calc.atree.tab.rb +0 -451
  84. data/examples/sample_calc/calc.cst.dr +0 -45
  85. data/examples/sample_calc/calc.cst.tab.rb +0 -644
  86. data/examples/sample_calc/calc.lex.tab.rb +0 -374
  87. data/examples/sample_calc/calc.nvaction.tab.rb +0 -465
  88. data/examples/sample_calc/calc.tab.rb +0 -365
  89. data/examples/sample_calc/calc_prec.nvaction.tab.rb +0 -431
  90. data/examples/slex_test/divreg.slex.tab.rb +0 -303
  91. data/examples/slex_test/ljoin.slex.tab.rb +0 -370
  92. data/lib/depager/ruby/plugins/_ast_tmpl.rb +0 -73
  93. data/lib/depager/ruby/plugins/action.rb +0 -43
  94. data/lib/depager/ruby/plugins/ast.dr +0 -269
  95. data/lib/depager/ruby/plugins/ast.rb +0 -1308
  96. data/lib/depager/ruby/plugins/astdf.rb +0 -6
  97. data/lib/depager/ruby/plugins/atree.dr +0 -55
  98. data/lib/depager/ruby/plugins/atree.rb +0 -347
  99. data/lib/depager/ruby/plugins/cst.rb +0 -626
  100. data/lib/depager/ruby/plugins/lex.rb +0 -336
  101. data/lib/depager/ruby/plugins/nvaction.rb +0 -19
  102. data/lib/depager/ruby/plugins/slex.rb +0 -817
  103. data/lib/depager/ruby/plugins/srp.rb +0 -51
  104. data/lib/depager/ruby/templates/simple.erb +0 -23
  105. data/setup.rb +0 -1585
  106. /data/examples/{sample_calc → tiny_calc}/test.calc +0 -0
@@ -0,0 +1,725 @@
1
+ %defext Depager::RieExtension
2
+ %extend Depager::Lexer ('depager/plugins/lex.rb')
3
+ %extend Depager::Action ('depager/plugins/action.rb')
4
+ %decorate @Action
5
+ #%decorate Depager::LALR::ShiftReducePrinter ('depager/plugins/srp.rb')
6
+ %inner{
7
+ require "pp"
8
+
9
+ module Nodes
10
+ N_THREAD = Struct.new :lineno, :targets, :excepts
11
+ N_TRANSFER = Struct.new :lineno, :targets, :excepts
12
+ N_EXCEPT = Struct.new :lineno, :let_or_ids
13
+ N_LET = Struct.new :lineno, :atoc, :expr, :state
14
+ N_ACTION = Struct.new :lineno, :expr
15
+ N_ATOC = Struct.new :lineno, :sym_name, :attr_name, :rx
16
+ end
17
+ include Nodes
18
+
19
+ begin
20
+ require 'depager/plugins/_rie_debug.rb' if Depager.debug_mode?
21
+ rescue LoadError
22
+ end
23
+
24
+ attr_accessor :action_code, :on_reduce, :semantics, :attributes, :ecs
25
+ attr_reader :grammar
26
+
27
+ def init_extension
28
+ @action_code = ''
29
+ @on_reduce = []
30
+ @on_state = []
31
+ @attributes = []
32
+ @semantics = [[]]
33
+ @locals = [{}]
34
+ @ecs = {}
35
+ if Depager.debug_mode?
36
+ path = g_parser.file == $stdin ? "stdin" : g_parser.file.path
37
+ @debug_output_path = "#{path}.rie_debug.output"
38
+ File.write @debug_output_path, ""
39
+ end
40
+ end
41
+
42
+ def term_extension
43
+ $grammar = @grammar = g_parser.table.grammar
44
+ expand_short_hand_notation
45
+ error_exit_if_error_pending
46
+
47
+ check_lattr
48
+ error_exit_if_error_pending
49
+ debug_info "locals:\n#{@locals.pretty_inspect}"
50
+
51
+ generate_action
52
+ g_parser.outer_code << generate_rie_decorator_code(@on_reduce, @on_state, @action_code)
53
+ end
54
+
55
+ def expand_short_hand_notation
56
+ semantics = []
57
+ @semantics.each_with_index do |rule_semantics, x|
58
+ res = []
59
+ (rule_semantics || []).each do |semantic|
60
+ case semantic
61
+ when N_TRANSFER ; expand_transfer res, semantic, grammar[x]
62
+ when N_THREAD ; expand_thread res, semantic, grammar[x]
63
+ else res << semantic
64
+ end
65
+ end
66
+ semantics << res
67
+ end
68
+ @semantics = semantics
69
+ end
70
+
71
+ def expand_transfer res, transfer, rule
72
+ lineno = transfer.lineno
73
+ transfer.targets.each do |attr_name|
74
+ unless @attributes[rule.lhs].include?(attr_name)
75
+ pending_error "#{attr_name} is not lhs attribute.", lineno
76
+ next
77
+ end
78
+ used = false
79
+ rule.rhs.each_with_index do |rsym, i|
80
+ next unless grammar.nonterm? rsym
81
+
82
+ rname = rule.rhs_names[i]
83
+ rattrs = @attributes[rsym] || []
84
+ next if !rattrs.include?(attr_name) || transfer.excepts.find do |e|
85
+ rname == e.sym_name and rattrs.include?(e.attr_name)
86
+ end
87
+ if attr_name[0] == ?_ # inherited attr
88
+ res << N_LET[lineno, N_ATOC[lineno, rname, attr_name, rule.n],
89
+ [N_ATOC[lineno, '$', attr_name, rule.n]]]
90
+ used = true
91
+ else
92
+ if used
93
+ pending_error "transfer `$.#{attr_name}' has too many source."
94
+ break
95
+ end
96
+ res << N_LET[lineno, N_ATOC[lineno, '$', attr_name, rule.n],
97
+ [N_ATOC[lineno, rname, attr_name, rule.n]]]
98
+ used = true
99
+ end
100
+ end
101
+ unless used
102
+ pending_error "no rhs symbol have attribute `#{attr_name}'", lineno
103
+ end
104
+ end
105
+ end
106
+
107
+ def expand_thread res, thread, rule
108
+ lineno, excepts = thread.lineno, thread.excepts.dup
109
+ thread.targets.each do |syn_name|
110
+ inh_name = '_' + syn_name
111
+ from, used = nil, false
112
+
113
+ lname = rule.lhs_name
114
+ lattrs = @attributes[rule.lhs]
115
+
116
+ if lattrs.include?(inh_name)
117
+ from = N_ATOC[lineno, '$', inh_name, rule.n]
118
+ end
119
+ rule.rhs.each_with_index do |rsym, i|
120
+ rname = rule.rhs_names[i]
121
+ rattrs = @attributes[rsym] || []
122
+
123
+ if from and rattrs.include? inh_name and
124
+ not excepts.find{|e| rname == e.sym_name && rattrs.include?(e.attr_name) }
125
+ res << N_LET[lineno, N_ATOC[lineno, rname, inh_name, rule.n], [from]]
126
+ used = true
127
+ end
128
+ if rattrs.include? syn_name
129
+ from = N_ATOC[lineno, rname, syn_name, rule.n]
130
+ end
131
+ end
132
+ if from and lattrs.include?(syn_name) and
133
+ not excepts.find{|e| lname == e.sym_name && lattrs.include?(e.attr_name) }
134
+ res << N_LET[lineno, N_ATOC[lineno, '$', syn_name, rule.n], [from]]
135
+ used = true
136
+ end
137
+ unless used
138
+ pending_error "no rhs symbol have attribute `#{syn_name}'", lineno
139
+ end
140
+ end
141
+ end
142
+
143
+ def check_lattr
144
+ @inhs_of_nonterms = []
145
+ @semantics.each_with_index do |rule_semantics, x|
146
+ rule = grammar[x]
147
+ assigned = {}
148
+ locals = @locals[rule.n] = {}
149
+ rule_semantics.each do |semantic|
150
+ semantic.is_a? N_LET and check_lattr_let semantic, rule, locals, assigned
151
+ end
152
+
153
+ next if x == 0
154
+ lineno = rule_semantics.last.lineno rescue 0
155
+ @attributes[rule.lhs].each do |a|
156
+ if a[0] != ?_ and not assigned[['$', a]]
157
+ pending_error "attribute `$.#{a}' is not assigned.", lineno
158
+ end
159
+ end
160
+ rule.rhs.each_with_index do |rsym, y|
161
+ next unless grammar.nonterm? rsym
162
+ rname = rule.rhs_names[y]
163
+ @attributes[rsym].each do |a|
164
+ if a[0] == ?_ and not assigned[[rname, a]]
165
+ pending_error "attribute `#{rname}.#{a}' is not assigned.", lineno
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ def check_lattr_let let, rule, locals, assigned
173
+ lineno = let.lineno
174
+ attr_name = let.atoc.attr_name
175
+ sym_name = let.atoc.sym_name
176
+
177
+ # left hand side of let
178
+ unless valid_atoc? let.atoc
179
+ pending_error "invalid attribute occurrence `#{sym_name}.#{attr_name}'.", lineno
180
+ return
181
+ end
182
+ if let.atoc.sym_name == '$' and inh_atoc?(let.atoc)
183
+ pending_error "cannot assign `$.#{attr_name}'(LHS INH).", lineno
184
+ return
185
+ elsif let.atoc.sym_name != '$' and syn_atoc?(let.atoc)
186
+ pending_error "cannot assign `#{sym_name}.#{attr_name}'(RHS SYN).", lineno
187
+ return
188
+ end
189
+ if local_atoc?(let.atoc)
190
+ if locals[attr_name]
191
+ warning "local attributes `#{attr_name}' is reassigned.", lineno
192
+ end
193
+ locals[attr_name] = 0
194
+ else
195
+ if assigned[[sym_name, attr_name]]
196
+ warning "attributes `#{sym_name}.#{attr_name}' is reassined.", lineno
197
+ else
198
+ assigned[[sym_name, attr_name]] = true
199
+ end
200
+ end
201
+
202
+ # right hand side of let
203
+ let.expr.find_all{|i| i.is_a? N_ATOC }.each do |expr_atoc|
204
+ unless valid_atoc? expr_atoc
205
+ next unless valid_atoc_name? expr_atoc # it is not atoc
206
+ pending_error "invalid attribute occurrence"<<
207
+ " `#{expr_atoc.sym_name}.#{expr_atoc.attr_name}'.", lineno
208
+ next
209
+ end
210
+ if expr_atoc.sym_name == '$' and syn_atoc?(expr_atoc)
211
+ pending_error "cannot refer `$.#{expr_atoc.attr_name}'(LHS SYN).", lineno
212
+ next
213
+ elsif expr_atoc.sym_name != '$' and inh_atoc?(expr_atoc)
214
+ pending_error "cannot refer `#{expr_atoc.sym_name}." <<
215
+ "#{expr_atoc.attr_name}'(RHS INH).", lineno
216
+ next
217
+ end
218
+ if local_atoc?(let.atoc)
219
+ if local_atoc?(expr_atoc) # local<-local
220
+ n = locals[expr_atoc.attr_name]
221
+ elsif syn_atoc?(expr_atoc) # local<-rsym.syn
222
+ n = rhs_index(expr_atoc)+1
223
+ else # local<-$.inh
224
+ n = 0
225
+ end
226
+ locals[attr_name] = n if locals[attr_name] < n
227
+ elsif sym_name != '$' and local_atoc?(expr_atoc) and # rhs<-local
228
+ rhs_index(let.atoc) <= locals[expr_atoc.attr_name]
229
+ pending_error "L-attribute violation.", lineno
230
+ next
231
+ elsif sym_name != '$' and expr_atoc.sym_name != '$' and # rhs<-rhs
232
+ rhs_index(let.atoc) <= rhs_index(expr_atoc)
233
+ pending_error "L-attribute violation.", lineno
234
+ next
235
+ end
236
+ end
237
+ end
238
+
239
+ def generate_action
240
+ # Actions on state change.
241
+ g_parser.table.states.each_with_index do |state, x|
242
+ actions = [ ]
243
+ inhs, locals = check_state_uniqueness(state)
244
+ inhs.each do |key, exprs| ; sym, attr_name = key
245
+ atoc = N_ATOC[0, "%#{sym}", attr_name]
246
+ actions << node_to_code(N_LET[0, atoc, exprs], state)
247
+ end
248
+ locals.each do |rx, attr_name, exprs|
249
+ atoc = N_ATOC[0, nil, attr_name, rx]
250
+ actions << node_to_code(N_LET[0, atoc, exprs], state)
251
+ end
252
+ unless actions.empty?
253
+ @action_code << "def _rie_state_#{x}\n #{actions.join("\n ")}\nend\n"
254
+ @on_state[x] = ":_rie_state_#{x}"
255
+ end
256
+ end
257
+
258
+ # Actions on reduce
259
+ @semantics.each_with_index do |rule_semantics, x|
260
+ actions = [ ]
261
+ rule = grammar[x]
262
+ rule_semantics.each do |semantic|
263
+ if semantic.is_a?(N_LET)
264
+ next if inh_atoc?(semantic.atoc)
265
+ next if local_atoc?(semantic.atoc) and not
266
+ @locals[x].find{|k,v| k == semantic.atoc.attr_name && v == rule.rhs.size }
267
+ end
268
+ code = node_to_code(semantic)
269
+ actions << code
270
+ end
271
+ unless actions.empty?
272
+ @action_code << "def _rie_reduce_#{x}\n #{actions.join("\n ")}\nend\n"
273
+ @on_reduce[x] = ":_rie_reduce_#{x}"
274
+ end
275
+ end
276
+ end
277
+
278
+ def node_to_code node, state=nil
279
+ case node
280
+ when N_LET
281
+ node_to_code(node.atoc, state) +" = "+
282
+ node_to_code(N_ACTION[0, node.expr], state)
283
+ when N_ACTION
284
+ node.expr.inject('') do |r, i|
285
+ r << (i.is_a?(N_ATOC) ? node_to_code(i, state) :
286
+ i.match(/^\s*[\{\[\(]$/) ? i : " #{i}")
287
+ end
288
+ when N_ATOC
289
+ return " #{node.sym_name}.#{node.attr_name}" unless valid_atoc? node
290
+ dot = 0
291
+ if state and item = state.closure.find{|i| i.rule.n == node.rx }
292
+ dot = item.n
293
+ elsif node.rx
294
+ dot = grammar[node.rx].rhs.size
295
+ end
296
+ if grammar.term? atoc_to_sym(node)
297
+ x = rhs_index(node) - dot
298
+ " _sstack(#{x}).syn.#{node.attr_name}"
299
+ elsif local_atoc? node
300
+ x = -dot
301
+ " _sstack(#{x-1}).local['#{node.attr_name}@#{node.rx}']"
302
+ elsif inh_atoc? node
303
+ # NEVER ASN LHS($).INH
304
+ if node.sym_name =~ /^%/ # ASN RHS.INH
305
+ x, sym = 0, $'
306
+ else # REF LHS($).INH / RHS.INH
307
+ x, sym = (rhs_index(node) || 0) - dot, atoc_to_sym(node)
308
+ end
309
+ ec = @ecs[[sym, node.attr_name]]
310
+ " _sstack(#{x-1}).inh['#{ec || sym}.#{node.attr_name}']"
311
+ else # syn_atoc?
312
+ # NEVER ASN RHS.SYN
313
+ if node.sym_name == '$' # ASN/REF LHS($).SYN
314
+ " @_rie_reduce_syn['#{node.attr_name}']"
315
+ else # REF RHS.SYN
316
+ x = rhs_index(node) - dot
317
+ " _sstack(#{x}).syn['#{node.attr_name}']"
318
+ end
319
+ end
320
+ else ; raise "cannot happen(#{node.inspect})."
321
+ end
322
+ rescue ; warn node.pretty_inspect ; raise
323
+ end
324
+
325
+ def check_state_uniqueness state
326
+ inhs, ec_inhs, locals = {}, {}, []
327
+ state.closure.each do |item|
328
+ rule = item.rule
329
+ @semantics[rule.n].each do |let|
330
+ next if !let.is_a?(N_LET)
331
+ next if item.n == rule.rhs.size
332
+ if local_atoc?(let.atoc)
333
+ @locals[rule.n].find{|k, v| k == let.atoc.attr_name && v == item.n } and
334
+ locals << [rule.n, let.atoc.attr_name, let.expr]
335
+ next
336
+ end
337
+ next if syn_atoc?(let.atoc) or rhs_index(let.atoc) != item.n
338
+
339
+ # ok, atoc is A._inh(B -> alpa _ A beta). set E_state(atoc).
340
+ attr_name = let.atoc.attr_name
341
+ sym = atoc_to_sym(let.atoc)
342
+ key = [sym, attr_name]
343
+ if expr = inhs[key]
344
+ if expr.size == 1 and expr[0].is_a?(N_ATOC) and
345
+ atoc_to_sym(expr[0]) == sym and expr[0].attr_name == attr_name
346
+ # older is self copy, update it.
347
+ inhs.delete(key)
348
+ inhs[key] = replace_atoc expr, inhs
349
+ elsif let.expr.size == 1 and let.expr[0].is_a?(N_ATOC) and
350
+ atoc_to_sym(let.expr[0]) == sym and let.expr[0].attr_name == attr_name
351
+ # newer is self copy, skip.
352
+ elsif not same_semantic? expr, let.expr
353
+ error_exit "LALR-attribute violation."
354
+ end
355
+ else
356
+ inhs[key] = replace_atoc let.expr, inhs
357
+ end
358
+ end
359
+ end
360
+
361
+ # check eclr
362
+ inhs.each do |k, v|
363
+ sym, attr_name = k
364
+ if ec = @ecs[k]
365
+ key = [ec, attr_name]
366
+ if ec_inhs[key]
367
+ unless same_semantic? ec_inhs[key], v
368
+ error_exit "ECLR-attribute violation."
369
+ end
370
+ else
371
+ ec_inhs[key] = v
372
+ end
373
+ else
374
+ ec_inhs[k] = v
375
+ end
376
+ end
377
+
378
+ debug_info "\n----------\n#{state}"
379
+ ec_inhs.each{|k,v| s,a=k;debug_info "#{grammar.symname s}:#{s}.#{a}=>#{v.pretty_inspect}" }
380
+ locals.each{|x,k,v| debug_info "#{x}.#{k}=>#{v.pretty_inspect}"}
381
+ return ec_inhs, locals
382
+ end
383
+
384
+ def same_semantic? sa, sb
385
+ return false unless sa.size == sb.size
386
+ sa.size.times do |x| a, b = sa[x], sb[x]
387
+ return false unless a.class == b.class
388
+ if a.is_a? N_ATOC
389
+ asym = a.sym_name == '$' ? atoc_to_sym(a) : a.sym_name
390
+ bsym = b.sym_name == '$' ? atoc_to_sym(b) : b.sym_name
391
+ asym = @ecs[[asym, a.attr_name]] if @ecs[[asym, a.attr_name]]
392
+ bsym = @ecs[[bsym, b.attr_name]] if @ecs[[bsym, b.attr_name]]
393
+ return false unless asym == bsym && a.attr_name == b.attr_name
394
+ else
395
+ return false unless a == b
396
+ end
397
+ end
398
+ return true
399
+ end
400
+
401
+ def replace_atoc expr, inhs={}
402
+ # warn "REPLACE:#{expr.pretty_inspect}"
403
+ res = []
404
+ expr and expr.each do |node|
405
+ if node.is_a? N_ATOC
406
+ if replace_to = inhs[[atoc_to_sym(node), node.attr_name]]
407
+ res.concat replace_to
408
+ else
409
+ res << node
410
+ end
411
+ elsif node.is_a? N_LET or node.is_a? N_ACTION
412
+ replaced = node.dup
413
+ replaced.expr = replace_atoc(node.expr, inhs)
414
+ res << replaced
415
+ else
416
+ res << node
417
+ end
418
+ end
419
+ # warn "=====>:#{res.pretty_inspect}"
420
+ return res
421
+ end
422
+
423
+ def valid_atoc_name? atoc
424
+ return true if local_atoc?(atoc)
425
+ return true if atoc.sym_name == '$'
426
+ return grammar[atoc.rx].rhs_name_to_sym(atoc.sym_name) ? true : false
427
+ end
428
+
429
+ def valid_atoc? atoc
430
+ return true if local_atoc?(atoc)
431
+ return true if atoc.sym_name =~ /^[%#]/
432
+ rule = grammar[atoc.rx]
433
+ sym = atoc.sym_name == '$' ? rule.lhs : rule.rhs_name_to_sym(atoc.sym_name)
434
+ return true if sym and atoc.sym_name =~ /^[A-Z]/ # term(no check)
435
+ sym and @attributes[sym] and @attributes[sym].include?(atoc.attr_name)
436
+ rescue ; warn "ATOC?:#{atoc.pretty_inspect}"; false
437
+ end
438
+
439
+ def rhs_index atoc
440
+ return nil if local_atoc?(atoc)
441
+ grammar[atoc.rx].rhs_names.index(atoc.sym_name)
442
+ end
443
+
444
+ def atoc_to_sym atoc
445
+ return nil if local_atoc?(atoc)
446
+ return $1.to_i if atoc.sym_name =~ /^%(\d+)$/
447
+ return grammar[atoc.rx].lhs if atoc.sym_name == '$'
448
+ grammar[atoc.rx].rhs_name_to_sym(atoc.sym_name) rescue nil
449
+ end
450
+
451
+ def local_atoc? atoc
452
+ atoc.sym_name == nil
453
+ end
454
+
455
+ def inh_atoc? atoc
456
+ !local_atoc?(atoc) and atoc.attr_name[0] == ?_
457
+ end
458
+
459
+ def syn_atoc? atoc
460
+ !local_atoc?(atoc) and atoc.attr_name[0] != ?_
461
+ end
462
+
463
+ def pending_error *args
464
+ @pending_errors ||= []
465
+ @pending_errors << g_parser.error_message(*args)
466
+ end
467
+
468
+ def error_exit_if_error_pending
469
+ @pending_errors and error_exit(@pending_errors.join("\n"))
470
+ end
471
+
472
+ def debug_info s
473
+ Depager.debug_mode? and File.open(@debug_output_path, 'a'){|f| f.write s}
474
+ end
475
+
476
+ def generate_rie_decorator_code on_reduce, on_state, action_code
477
+ on_reduce_code = on_reduce.map{|i| " #{i||'nil'},\n"}
478
+ on_state_code = on_state.map{|i| " #{i||'nil'},\n"}
479
+
480
+ generate_decorator_code(decorator_name, "#{d_parser.parsing_method}::AdvancedParser", <<-CODE)
481
+ on_reduce = [\n#{on_reduce_code.join}
482
+ ]
483
+ on_state = [\n#{on_state_code.join}
484
+ ]
485
+ Tables = [on_reduce, on_state]
486
+ RieATTR = Struct.new(:inh, :syn, :local)
487
+ def initialize inside
488
+ super inside
489
+ @on_reduce, @on_state = self.class::Tables
490
+ end
491
+ def before_parse
492
+ after_shift
493
+ end
494
+ def after_shift
495
+ msg = @on_state[stack.last] and send(msg)
496
+ end
497
+ def before_reduce
498
+ stack.last == 0 and after_shift
499
+ @_rie_reduce_syn = {}
500
+ mes = @on_reduce[-action_value] and send(mes)
501
+ end
502
+ require 'pp'
503
+ def after_reduce
504
+ _sstack(-1); stack[-2][decorator_index].syn = @_rie_reduce_syn
505
+ after_shift
506
+ end
507
+ def _sstack n
508
+ n = n * 2
509
+ if -n == stack.size + 1
510
+ @_attr_for_state0 ||= RieATTR[{}, {}, {}]
511
+ else
512
+ stack[n][decorator_index] ||= RieATTR[{}, stack[n][1] == :NT ? {} : stack[n][1], {}]
513
+ end
514
+ rescue
515
+ warn "N:\#{n}"
516
+ raise
517
+ end
518
+ \n#{action_code}
519
+ CODE
520
+ end
521
+ %}
522
+ %hook post_lhs /\[/
523
+ %banner '[...]'
524
+ %inner{
525
+ def do_default
526
+ master.attributes[g_parser.lhs] = []
527
+ end
528
+ %}
529
+ %%
530
+ %LEX{
531
+ /\s+/ { }
532
+ /[a-zA-Z_]\w*/ { yield token(:ID, $&) }
533
+ ']' { yield token(']'); yield token(nil) }
534
+ /./ { yield token($&) }
535
+ %}
536
+ #begin-rule
537
+ start:
538
+ '[' attr_list ']' { master.attributes[g_parser.lhs] = _attr_list }
539
+ ;
540
+ attr_list:
541
+ attr { [ _attr ] }
542
+ | attr_list ',' attr
543
+ {
544
+ if _attr_list.include? _attr
545
+ warning "attribute `#{_attr}' reappeared."
546
+ _attr_list
547
+ else
548
+ _attr_list << _attr
549
+ end
550
+ }
551
+ ;
552
+ attr:
553
+ ID { _ID.value }
554
+ | ID ':' ID-ec
555
+ {
556
+ unless _ID.value[0] == ?_
557
+ error_exit "EC must be inherited attribute.", _ec.lineno
558
+ else
559
+ master.ecs[[g_parser.lhs, _ID.value]] = _ec.value
560
+ end
561
+ _ID.value
562
+ }
563
+ ;
564
+ #end-rule
565
+ %%
566
+ %hook post_rhs /\{/
567
+ %banner '{...}'
568
+ %inner{
569
+ attr_accessor :locals
570
+ def before_parse
571
+ @nest = 0
572
+ @locals = {}
573
+ end
574
+ def do_default
575
+ master.semantics[g_parser.rules.size-1] = []
576
+ end
577
+ def skip_space
578
+ begin
579
+ @line.match(/^[\s\n]+(#[.\n]*)?/) and @line = $'
580
+ break unless @line.empty?
581
+ end while @original_line = @line = getline
582
+ end
583
+ def getline
584
+ begin ; line = @file.gets
585
+ end while line and line =~ /^\s*(#.*)?$/
586
+ line
587
+ end
588
+ %}
589
+ %prec{
590
+ left '.'
591
+ left ID
592
+ %}
593
+ %%
594
+ %LEX{
595
+ /#.*/ { }
596
+ /[ \t]+/ { }
597
+ /\r?\n/ { yield token(';') }
598
+ /\s*\(/ { yield token('(', $&) ; skip_space }
599
+ /\s*\[/ { yield token('[', $&) ; skip_space }
600
+ /\s*\{/ { yield token('{', $&) ; skip_space ; @nest +=1 }
601
+ '}' { yield token('}'); (@nest-=1) == 0 and yield token(nil) }
602
+ '.' { yield token('.') ; @_mode = :AFTER_DOT }
603
+ ',' { yield token(','); @line.match(/[\s\n]*/) and @line = $' } #'
604
+ '%transfer' { yield token(:TRANSFER) }
605
+ '%thread' { yield token(:THREAD) }
606
+ '%except' { yield token(:EXCEPT) }
607
+ '$.' { yield token(:ID, '$'); yield token('.') ; @_mode = :AFTER_DOT }
608
+ /'([^'\\]+|\\.)*'/,
609
+ /"([^"\\]+|\\.)*"/,
610
+ /\/([^\/\\]+|\\.)*\//,
611
+ /(@|$|:)[a-zA-Z_]\w*/,
612
+ /[a-zA-Z_]\w*[!?]/,
613
+ /\d+/ { yield token(:RBTOKEN, $&) }
614
+ /(<=|>=|=>|==|===|!=|and|or)/,
615
+ /([+!~*\-\/%^<>&|?:]+|\.\.\.?)/
616
+ { yield token(:RBTOKEN, $&) ; skip_space }
617
+ '=' { yield token('=') ; skip_space }
618
+ /[a-zA-Z_]\w*/
619
+ {
620
+ if @_mode != :AFTER_DOT and @locals[$&]
621
+ yield token(:LID, $&)
622
+ else
623
+ @_mode = nil
624
+ yield token(:ID, $&)
625
+ end
626
+ }
627
+ /./ { yield token($&) }
628
+ %}
629
+ %ACTION{
630
+ include Depager::RieExtension::Nodes
631
+ %}
632
+ #begin-rule
633
+ start:
634
+ '{' stmt_list '}'
635
+ {
636
+ basis.locals.clear
637
+ master.semantics[g_parser.rules.size-1] = _stmt_list.compact
638
+ }
639
+ ;
640
+
641
+ # stmt
642
+ stmt_list:
643
+ stmt
644
+ {
645
+ if _stmt.is_a? N_EXCEPT
646
+ error_exit "invalid %except.", _stmt.lineno
647
+ end
648
+ [ _stmt ]
649
+ }
650
+ | stmt_list ';' stmt
651
+ {
652
+ if _stmt.is_a? N_EXCEPT
653
+ unless [N_THREAD, N_TRANSFER].include?(_stmt_list.last.class)
654
+ error_exit "invalid %except.", _stmt.lineno
655
+ end
656
+ let_or_ids = _stmt.let_or_ids
657
+ if let_or_ids.is_a? N_LET
658
+ _stmt_list.last.excepts << let_or_ids.atoc
659
+ _stmt_list.insert(_stmt_list.size-1, let_or_ids)
660
+ else
661
+ _stmt_list.last.excepts.concat(let_or_ids)
662
+ _stmt_list
663
+ end
664
+ else
665
+ _stmt ? (_stmt_list << _stmt) : _stmt_list
666
+ end
667
+ }
668
+ ;
669
+ stmt:
670
+ { nil }
671
+ | THREAD id_list { N_THREAD[val[0].lineno, _id_list, []] }
672
+ | TRANSFER id_list { N_TRANSFER[val[0].lineno, _id_list, []] }
673
+ | EXCEPT lhs_list { N_EXCEPT[val[0].lineno, lhs_list] }
674
+ | EXCEPT lhs '=' rbexpr { N_EXCEPT[val[0].lineno, N_LET[_lhs.lineno, _lhs, _rbexpr]]}
675
+ | lhs '=' rbexpr { N_LET[_lhs.lineno, _lhs, _rbexpr] }
676
+ | LID '=' rbexpr
677
+ {
678
+ N_LET[val[0].lineno, N_ATOC[val[0].lineno, nil, _LID.value, g_parser.rules.size-1], _rbexpr]
679
+ }
680
+ | ID '=' rbexpr
681
+ {
682
+ basis.locals[_ID.value] = true
683
+ N_LET[val[0].lineno, N_ATOC[val[0].lineno, nil, _ID.value, g_parser.rules.size-1], _rbexpr]
684
+ }
685
+ | rbexpr { N_ACTION[basis.file.lineno, _rbexpr ] }
686
+ ;
687
+ # rbexpr
688
+ rbexpr_list:
689
+ rbexpr { _rbexpr }
690
+ | rbexpr_list ';' { _rbexpr_list }
691
+ | rbexpr_list ';' rbexpr { (_rbexpr_list << ';').concat _rbexpr}
692
+ ;
693
+ rbexpr:
694
+ rbelem { _rbelem }
695
+ | rbexpr rbelem { _rbexpr.concat _rbelem }
696
+ ;
697
+ rbelem:
698
+ lhs { [_lhs] }
699
+ | ID { [_ID.value] }
700
+ | LID { [ N_ATOC[_LID.lineno, nil, _LID.value, g_parser.rules.size-1] ] }
701
+ | RBTOKEN { [_RBTOKEN.value] }
702
+ | '.' { ['.'] }
703
+ | ',' { [','] }
704
+ | '[' ']' { [ val[0].value, ']' ] }
705
+ | '[' rbexpr_list ']' { [ val[0].value ].concat(_rbexpr_list) << ']' }
706
+ | '{' '}' { [ val[0].value, '}' ]}
707
+ | '{' rbexpr_list '}' { [ val[0].value ].concat(_rbexpr_list) << '}' }
708
+ | '(' ')' { [ val[0].value, ')' ]}
709
+ | '(' rbexpr_list ')' { [ val[0].value ].concat(_rbexpr_list) << ')' }
710
+ ;
711
+
712
+ # lhs
713
+ lhs_list:
714
+ lhs { [ _lhs ]}
715
+ | lhs_list ',' lhs { lhs_list << lhs }
716
+ ;
717
+ lhs:
718
+ ID '.' ID-attr { N_ATOC[_ID.lineno, _ID.value, _attr.value, g_parser.rules.size-1] }
719
+ ;
720
+ id_list:
721
+ ID { [ _ID.value ] }
722
+ | id_list ',' ID { _id_list << _ID.value }
723
+ ;
724
+ #end-rule
725
+ %%