depager 0.2.3 → 0.3.0.b20160729

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