depager 0.3.0.b20160729 → 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.
- checksums.yaml +5 -5
- data/.rubocop.yml +44 -0
- data/.simplecov +5 -0
- data/Gemfile +12 -0
- data/LICENSE.gpl +339 -0
- data/Manifest.txt +73 -0
- data/README.en +4 -3
- data/README.ja +4 -47
- data/Rakefile +31 -0
- data/bin/depager +3 -38
- data/examples/action_pl0d/pl0d.action.dr +4 -4
- data/examples/action_pl0d/test.pl0ds +2 -3
- data/examples/c89/c89.dr +4 -4
- data/examples/c89/test.c89 +1 -1
- data/examples/extension/astdf.rb +4 -5
- data/examples/extension/atree.dr +3 -3
- data/examples/extension/calc.atree.dr +4 -4
- data/examples/extension/calc.simple_action.dr +3 -3
- data/examples/extension/paction.dr +3 -3
- data/examples/extension/pactiontest.dr +3 -3
- data/examples/extension/simple_action.rb +26 -24
- data/examples/pl0d/pl0ds.dr +5 -5
- data/examples/pl0d/test.pl0ds +2 -2
- data/examples/rie_calc/calc.rie.dr +4 -4
- data/examples/rie_dcuse/dcuse.rie.dr +4 -4
- data/examples/rie_pl0/pl0.rie.dr +3 -3
- data/examples/slex_test/divreg.slex.dr +5 -5
- data/examples/slex_test/ljoin.slex.dr +5 -5
- data/examples/{sample_calc → tiny_calc}/calc.action.dr +4 -4
- data/examples/{sample_calc → tiny_calc}/calc.ast.action.dr +20 -9
- data/examples/{sample_calc → tiny_calc}/calc.ast.dr +19 -7
- data/examples/{sample_calc → tiny_calc}/calc.cst.dr +12 -7
- data/examples/{sample_calc → tiny_calc}/calc.dr +1 -1
- data/examples/{sample_calc → tiny_calc}/calc.lex.dr +2 -2
- data/examples/{sample_calc → tiny_calc}/calc_prec.action.dr +4 -4
- data/lib/depager/cli.rb +44 -0
- data/lib/depager/grammar.rb +72 -75
- data/lib/depager/lr.rb +169 -154
- data/lib/depager/parser.rb +90 -103
- data/lib/depager/plugins/_rie_debug.rb +63 -0
- data/lib/depager/plugins/action.rb +47 -0
- data/lib/depager/{ruby/plugins → plugins}/ast.dr +20 -17
- data/lib/depager/{ruby/plugins → plugins}/ast.rb +266 -304
- data/lib/depager/{ruby/plugins → plugins}/cst.dr +18 -16
- data/lib/depager/{ruby/plugins → plugins}/cst.rb +152 -148
- data/lib/depager/{ruby/plugins → plugins}/lex.dr +7 -7
- data/lib/depager/{ruby/plugins → plugins}/lex.rb +72 -69
- data/lib/depager/{ruby/plugins → plugins}/rie.dr +12 -10
- data/lib/depager/{ruby/plugins → plugins}/rie.rb +224 -263
- data/lib/depager/{ruby/plugins → plugins}/slex.dr +13 -14
- data/lib/depager/{ruby/plugins → plugins}/slex.rb +183 -194
- data/lib/depager/plugins/srp.rb +46 -0
- data/lib/depager/ruby/templates/extension_lalr_master.erb +6 -12
- data/lib/depager/ruby/templates/extension_lalr_slave.erb +31 -17
- data/lib/depager/ruby/templates/single_lalr_parser.erb +35 -26
- data/lib/depager/utils.rb +56 -46
- data/lib/depager/version.rb +1 -2
- data/lib/depager.rb +166 -176
- metadata +38 -33
- data/lib/depager/ruby/plugins/_rie_debug.rb +0 -35
- data/lib/depager/ruby/plugins/action.rb +0 -53
- data/lib/depager/ruby/plugins/srp.rb +0 -56
- /data/examples/{sample_calc → tiny_calc}/test.calc +0 -0
data/lib/depager.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require "depager/
|
4
|
-
require "depager/
|
5
|
-
require "depager/utils.rb"
|
1
|
+
require "erb"
|
2
|
+
require "depager/parser"
|
3
|
+
require "depager/grammar"
|
4
|
+
require "depager/utils"
|
6
5
|
|
7
6
|
module Depager
|
8
7
|
def self.configuration
|
9
|
-
@
|
8
|
+
@configuration ||= {}
|
10
9
|
end
|
11
10
|
|
12
|
-
def self.debug_mode?
|
11
|
+
def self.debug_mode?(flag = "")
|
13
12
|
value = configuration[:debug] or return false
|
14
|
-
!!
|
13
|
+
!!value.match(/#{flag}/)
|
15
14
|
end
|
16
15
|
|
17
16
|
def self.verbose_mode?
|
@@ -28,21 +27,21 @@ module Depager
|
|
28
27
|
@g_parser = GrammarPartParser.new(self)
|
29
28
|
|
30
29
|
until file.eof?
|
31
|
-
case
|
30
|
+
case file.gets
|
32
31
|
when /^\s*(#.*)?$/
|
33
|
-
#skip space and comment.
|
32
|
+
# skip space and comment.
|
34
33
|
when /^%class\s+(\S+)(\s+based_on\s+(\S+)(\s+\(\s*'(.+)'\s*\))?)?\s*$/
|
35
34
|
@target_name = $1
|
36
35
|
if $2
|
37
36
|
require $5 if $5
|
38
|
-
nesting = $3.split(
|
39
|
-
generator_class = nesting.inject(Object){|c,name| c.const_get(name) }
|
37
|
+
nesting = $3.split("::").tap { |it| it[-1] = "#{it[-1]}Generator" }
|
38
|
+
generator_class = nesting.inject(Object) { |c, name| c.const_get(name) }
|
40
39
|
else
|
41
|
-
require
|
40
|
+
require "depager/lr"
|
42
41
|
generator_class = LALR::ParserGenerator
|
43
42
|
end
|
44
43
|
|
45
|
-
if @target_name
|
44
|
+
if @target_name =~ /(.+)::([^:]+)/
|
46
45
|
@target_namespace = $1
|
47
46
|
@target_name = $2
|
48
47
|
else
|
@@ -52,10 +51,10 @@ module Depager
|
|
52
51
|
@generator = generator_class.new(self)
|
53
52
|
break
|
54
53
|
when /^%defext\s+(\S+)\s*$/
|
55
|
-
require
|
54
|
+
require "depager/lr"
|
56
55
|
|
57
56
|
@target_namespace = $1
|
58
|
-
@target_name =
|
57
|
+
@target_name = "Master"
|
59
58
|
|
60
59
|
@generator = LALR::ExtensionGenerator.new(self)
|
61
60
|
break
|
@@ -76,36 +75,34 @@ module Depager
|
|
76
75
|
|
77
76
|
Token = Struct.new(:tag, :value, :name, :lineno)
|
78
77
|
|
79
|
-
HOOK_KEYS = [
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
]
|
87
|
-
|
88
|
-
attr_accessor :rules, :terms, :nonterms, :precs, :table
|
89
|
-
|
90
|
-
attr_accessor :line, :original_line, :old_line, :token
|
91
|
-
attr_accessor :outer_code, :inner_code, :mixins
|
78
|
+
HOOK_KEYS = %i[
|
79
|
+
pre_rule_list post_rule_list
|
80
|
+
pre_rule post_rule
|
81
|
+
post_lhs
|
82
|
+
post_rhs_list pre_rhs_list
|
83
|
+
pre_rhs post_rhs
|
84
|
+
post_symbol
|
85
|
+
].freeze # :nodoc:
|
86
|
+
|
87
|
+
attr_accessor :rules, :terms, :nonterms, :precs, :table, :lhs, :rhs, :nrhs, :rhs_names, :nrules, :line,
|
88
|
+
:original_line, :old_line, :token, :outer_code, :inner_code, :mixins
|
92
89
|
attr_reader :d_parser, :target_namespace, :target_name, :hooks
|
93
90
|
|
94
|
-
def initialize
|
91
|
+
def initialize(d_parser)
|
95
92
|
@d_parser = d_parser
|
96
93
|
end
|
97
94
|
|
98
95
|
# parse and make LALR(1) table
|
99
96
|
def parse(full_target_name, precs = [], extensions = [], options = {})
|
100
|
-
@original_line = @old_line = @line =
|
101
|
-
@inner_code =
|
102
|
-
@outer_code =
|
97
|
+
@original_line = @old_line = @line = ""
|
98
|
+
@inner_code = ""
|
99
|
+
@outer_code = ""
|
103
100
|
|
104
101
|
full_target_name.match(/::([^:]+)$/) or raise
|
105
102
|
@target_namespace = $`
|
106
103
|
@target_name = $1
|
107
104
|
|
108
|
-
|
105
|
+
extend_parser(extensions, options)
|
109
106
|
init_grammar
|
110
107
|
parse_grammar
|
111
108
|
check_grammar
|
@@ -114,20 +111,20 @@ module Depager
|
|
114
111
|
grammar = d_parser.parsing_method::Grammar.new(@rules, @terms, @nonterms, @precs)
|
115
112
|
@table = d_parser.parsing_method::Table.new(grammar)
|
116
113
|
@table.check_table d_parser
|
117
|
-
@extensions.each{|o| o.send :term_extension }
|
114
|
+
@extensions.each { |o| o.send :term_extension }
|
118
115
|
@table
|
119
116
|
end
|
120
117
|
|
121
|
-
def hook_name?
|
118
|
+
def hook_name?(s)
|
122
119
|
HOOK_KEYS.include? s.to_sym
|
123
120
|
end
|
124
121
|
|
125
|
-
def update_context
|
122
|
+
def update_context(line)
|
126
123
|
@line = line
|
127
|
-
|
124
|
+
scan_token
|
128
125
|
end
|
129
126
|
|
130
|
-
def int_to_sym
|
127
|
+
def int_to_sym(n)
|
131
128
|
@int_to_sym[n]
|
132
129
|
end
|
133
130
|
|
@@ -135,116 +132,114 @@ module Depager
|
|
135
132
|
int_to_sym(lhs)
|
136
133
|
end
|
137
134
|
|
138
|
-
def add_nonterm
|
135
|
+
def add_nonterm(sym)
|
139
136
|
sym = sym.to_s.intern
|
140
137
|
isym = @nonterms[sym] = @nonterms.size
|
141
138
|
@int_to_sym[isym] = sym
|
142
|
-
|
139
|
+
isym
|
143
140
|
end
|
144
141
|
|
145
|
-
def add_rule
|
142
|
+
def add_rule(lhs, rhs, prec = nil, rhs_names = nil)
|
146
143
|
@lhs_syms[lhs] = true
|
147
|
-
rule =
|
144
|
+
rule = d_parser.parsing_method::Rule[lhs, rhs, prec, rhs_names]
|
148
145
|
@rules.push rule
|
149
|
-
|
146
|
+
rule
|
150
147
|
end
|
151
148
|
|
152
|
-
def name_to_rhs_index
|
149
|
+
def name_to_rhs_index(name)
|
153
150
|
@rhs_names.index(name)
|
154
151
|
end
|
155
152
|
|
156
|
-
def insert_sym_to_rhs
|
153
|
+
def insert_sym_to_rhs(pos, token_value, token_name)
|
157
154
|
if pos < 0
|
158
155
|
@rhs.push token_value
|
159
156
|
@rhs_names[@rhs.size - 1] = token_name
|
160
|
-
@rhs_syms[token_value] = true
|
161
157
|
else
|
162
158
|
@rhs.insert(pos, token_value)
|
163
159
|
@rhs_names.insert(pos, token_name)
|
164
|
-
@rhs_syms[token_value] = true
|
165
160
|
end
|
161
|
+
@rhs_syms[token_value] = true
|
166
162
|
end
|
167
163
|
|
168
164
|
private
|
165
|
+
|
169
166
|
def parse_grammar
|
170
|
-
|
167
|
+
scan_token
|
171
168
|
do_hook :pre_rule_list
|
172
169
|
parse_rulelist
|
173
170
|
do_hook :post_rule_list
|
174
|
-
|
175
|
-
|
176
|
-
|
171
|
+
return if @token.tag.nil?
|
172
|
+
|
173
|
+
error_exit "syntax error(grammar). unexpected '#{@token.tag}' expect '%%'"
|
177
174
|
end
|
178
175
|
|
179
176
|
def parse_rulelist
|
180
177
|
do_hook :pre_rule
|
181
178
|
parse_rule
|
182
179
|
do_hook :post_rule
|
183
|
-
|
184
|
-
|
185
|
-
|
180
|
+
return unless @token.tag == :NT
|
181
|
+
|
182
|
+
parse_rulelist
|
186
183
|
end
|
187
184
|
|
188
185
|
def parse_rule
|
189
|
-
|
190
|
-
@lhs = @token.value
|
186
|
+
return unless @token[0] == :NT
|
191
187
|
|
192
|
-
|
193
|
-
do_hook :post_lhs
|
188
|
+
@lhs = @token.value
|
194
189
|
|
195
|
-
|
196
|
-
|
197
|
-
end
|
198
|
-
get_token
|
190
|
+
scan_token
|
191
|
+
do_hook :post_lhs
|
199
192
|
|
200
|
-
|
201
|
-
|
202
|
-
parse_rhslist
|
203
|
-
do_hook :post_rhs_list
|
193
|
+
error_exit "syntax error(grammar). unexpected '#{@token.tag}' expecting ':'" unless @token.tag == ":"
|
194
|
+
scan_token
|
204
195
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
196
|
+
@nrhs = 0
|
197
|
+
do_hook :pre_rhs_list
|
198
|
+
parse_rhslist
|
199
|
+
do_hook :post_rhs_list
|
200
|
+
|
201
|
+
error_exit "syntax error(grammar). unexpected '#{@token.tag}' expecting ';'" unless @token.tag == ";"
|
202
|
+
scan_token
|
210
203
|
end
|
211
204
|
|
212
205
|
def parse_rhslist
|
213
|
-
@rhs = []
|
206
|
+
@rhs = []
|
207
|
+
@rhs_names = []
|
208
|
+
@prec = nil
|
214
209
|
do_hook :pre_rhs
|
215
210
|
parse_syms
|
216
211
|
add_rule(@lhs, @rhs, @prec, @rhs_names)
|
217
212
|
do_hook :post_rhs
|
218
213
|
@nrhs += 1
|
219
214
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
215
|
+
return unless @token.tag == "|"
|
216
|
+
|
217
|
+
scan_token
|
218
|
+
parse_rhslist
|
224
219
|
end
|
225
220
|
|
226
221
|
def parse_syms
|
227
|
-
|
228
|
-
insert_sym_to_rhs(-1, @token.value, @token.name)
|
229
|
-
get_token
|
222
|
+
return unless @token.tag == :NT || @token.tag == :T
|
230
223
|
|
231
|
-
|
232
|
-
|
233
|
-
|
224
|
+
insert_sym_to_rhs(-1, @token.value, @token.name)
|
225
|
+
scan_token
|
226
|
+
|
227
|
+
do_hook :post_symbol
|
228
|
+
parse_syms
|
234
229
|
end
|
235
230
|
|
236
|
-
def make_token
|
231
|
+
def make_token(tag, value, name = nil)
|
237
232
|
@token = Token.new(tag, value, name, file.lineno)
|
238
233
|
end
|
239
234
|
|
240
|
-
def
|
235
|
+
def scan_token
|
241
236
|
while !@line.empty? || !file.eof?
|
242
237
|
@original_line = @old_line = @line = file.gets if @line.empty?
|
243
238
|
|
244
239
|
tag = s = name = val = nil
|
245
|
-
until @line.empty?
|
240
|
+
until @line.empty?
|
246
241
|
case @line
|
247
|
-
when /^\s+/, /^\#.*/
|
242
|
+
when /^\s+/, /^\#.*/
|
248
243
|
# skip
|
249
244
|
when /^=([a-zA-Z]+)/
|
250
245
|
@prec = s = $1.intern
|
@@ -252,17 +247,17 @@ module Depager
|
|
252
247
|
when /^([a-z][a-z0-9_]*)(-([a-z][_a-z0-9]*))?/
|
253
248
|
tag = :NT
|
254
249
|
s = $1.intern
|
255
|
-
name = $3
|
250
|
+
name = $3 || $1
|
256
251
|
val = @nonterms[s] ||= @nonterms.size
|
257
252
|
when /^([A-Z][A-Z0-9_]*)(-([a-z][_a-z0-9]*))?/
|
258
253
|
tag = :T
|
259
254
|
s = $1.intern
|
260
|
-
name = $3
|
261
|
-
val = @terms[s] ||=
|
255
|
+
name = $3 || $1
|
256
|
+
val = @terms[s] ||= - (@terms.size + 1)
|
262
257
|
when /^'(.+?)'/
|
263
258
|
tag = :T
|
264
259
|
name = s = $1
|
265
|
-
val = @terms[s] ||=
|
260
|
+
val = @terms[s] ||= - (@terms.size + 1)
|
266
261
|
when /^%%/
|
267
262
|
return make_token(nil, nil)
|
268
263
|
when /^([:;|])/
|
@@ -271,32 +266,31 @@ module Depager
|
|
271
266
|
else
|
272
267
|
return make_token(:UNKNOWN, @line[0].chr)
|
273
268
|
end
|
274
|
-
@old_line
|
269
|
+
@old_line = @line
|
270
|
+
@line = $'
|
275
271
|
@int_to_sym[val] ||= s if val && s
|
276
272
|
return make_token(tag, val, name) if tag
|
277
273
|
end
|
278
274
|
end
|
279
|
-
|
275
|
+
make_token(nil, nil)
|
280
276
|
end
|
281
277
|
|
282
|
-
def
|
278
|
+
def extend_parser(extensions, options)
|
283
279
|
init_hook
|
284
280
|
@extensions = []
|
285
281
|
extensions.each do |f, m|
|
286
|
-
if f
|
282
|
+
if f&.match(%r{^\./})
|
287
283
|
require File.expand_path(f, File.dirname(file.path))
|
288
284
|
elsif f
|
289
285
|
require f
|
290
286
|
end
|
291
287
|
|
292
|
-
nesting = m.split(
|
293
|
-
extension = nesting.inject(Object){|c,name| c.const_get(name) }.new
|
294
|
-
options[m]
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
warning "no such a option '#{m}.#{k}'."
|
299
|
-
end
|
288
|
+
nesting = m.split("::").tap { |it| it[-1] = "#{it[-1]}Extension" }
|
289
|
+
extension = nesting.inject(Object) { |c, name| c.const_get(name) }.new
|
290
|
+
options[m]&.each do |k, v|
|
291
|
+
extension.send(:"#{k}=", v)
|
292
|
+
rescue NoMethodError
|
293
|
+
warning "no such a option '#{m}.#{k}'."
|
300
294
|
end
|
301
295
|
@extensions << extension
|
302
296
|
extension.extension_registered self
|
@@ -305,17 +299,17 @@ module Depager
|
|
305
299
|
end
|
306
300
|
|
307
301
|
def init_grammar
|
308
|
-
@rules = [
|
302
|
+
@rules = [d_parser.parsing_method::Rule[0, [1]]]
|
309
303
|
@terms = { nil => -1, false => -2 }
|
310
|
-
@nonterms = {
|
304
|
+
@nonterms = { "$start" => 0 }
|
311
305
|
@int_to_sym = {}
|
312
306
|
@rhs_syms = {}
|
313
307
|
@lhs_syms = {}
|
314
308
|
end
|
315
309
|
|
316
|
-
def make_grammar
|
310
|
+
def make_grammar(precs)
|
317
311
|
ts = @nonterms.size - 1
|
318
|
-
@terms.each{|k,v| @terms[k] = ts - v}
|
312
|
+
@terms.each { |k, v| @terms[k] = ts - v }
|
319
313
|
|
320
314
|
@precs = {}
|
321
315
|
precs.each_with_index do |p, x|
|
@@ -328,19 +322,19 @@ module Depager
|
|
328
322
|
end
|
329
323
|
end
|
330
324
|
@rules.each do |rule|
|
331
|
-
rule.rhs.each_with_index{|i, x| rule.rhs[x] = ts - i if i < 0}
|
325
|
+
rule.rhs.each_with_index { |i, x| rule.rhs[x] = ts - i if i < 0 }
|
332
326
|
rule.prec &&= @precs[@terms[rule.prec]]
|
333
327
|
end
|
334
328
|
end
|
335
329
|
|
336
330
|
def check_grammar
|
337
331
|
lhs_warns = []
|
338
|
-
@lhs_syms.
|
339
|
-
lhs_warns << s if s != 1
|
332
|
+
@lhs_syms.each_key do |s|
|
333
|
+
lhs_warns << s if (s != 1) && !@rhs_syms[s]
|
340
334
|
end
|
341
335
|
rhs_warns = []
|
342
|
-
@rhs_syms.
|
343
|
-
rhs_warns << s if s > 0
|
336
|
+
@rhs_syms.each_key do |s|
|
337
|
+
rhs_warns << s if (s > 0) && !@lhs_syms[s]
|
344
338
|
end
|
345
339
|
lhs_warns.uniq.each do |s|
|
346
340
|
warning "the lhs '#{@int_to_sym[s]}' is not used"
|
@@ -351,24 +345,25 @@ module Depager
|
|
351
345
|
end
|
352
346
|
|
353
347
|
def init_hook
|
354
|
-
@hooks = HOOK_KEYS.
|
348
|
+
@hooks = HOOK_KEYS.each_with_object({}) do |i, r|
|
349
|
+
r[i] = []
|
350
|
+
end
|
355
351
|
end
|
356
352
|
|
357
|
-
def do_hook
|
358
|
-
@hooks[hook].each{|o, m| o.send m}
|
353
|
+
def do_hook(hook)
|
354
|
+
@hooks[hook].each { |o, m| o.send m }
|
359
355
|
end
|
360
356
|
end
|
361
357
|
|
362
358
|
class Generator
|
363
359
|
include Depager::Utils::CommonMethods
|
364
360
|
|
365
|
-
TEMPLATES_DIR = File.expand_path(
|
361
|
+
TEMPLATES_DIR = File.expand_path("depager/ruby/templates", __dir__)
|
366
362
|
|
367
363
|
attr_reader :d_parser, :g_parser, :parsing_method
|
368
|
-
attr_accessor :outer_code, :inner_code
|
369
|
-
attr_accessor :decorators, :requirements, :options
|
364
|
+
attr_accessor :outer_code, :inner_code, :setup_code, :decorators, :requirements, :options
|
370
365
|
|
371
|
-
def initialize
|
366
|
+
def initialize(d_parser)
|
372
367
|
@d_parser = d_parser
|
373
368
|
@g_parser = d_parser.g_parser
|
374
369
|
@parsing_method = nil
|
@@ -377,14 +372,15 @@ module Depager
|
|
377
372
|
@decorators = []
|
378
373
|
@requirements = []
|
379
374
|
@extensions = []
|
380
|
-
@inner_code =
|
381
|
-
@outer_code =
|
375
|
+
@inner_code = ""
|
376
|
+
@outer_code = ""
|
377
|
+
@setup_code = ""
|
382
378
|
@precs = []
|
383
379
|
@mixins = []
|
384
380
|
end
|
385
381
|
|
386
|
-
def generate_code
|
387
|
-
ERB.new(template ||
|
382
|
+
def generate_code(template)
|
383
|
+
ERB.new(template || "", trim_mode: "-").result(binding)
|
388
384
|
end
|
389
385
|
|
390
386
|
def parse_prec
|
@@ -395,7 +391,7 @@ module Depager
|
|
395
391
|
# skip
|
396
392
|
when /^\s*(left|right|nonassoc)\s+(.*)$/
|
397
393
|
dir = $1.upcase.intern
|
398
|
-
syms = $2.split.map{|i|
|
394
|
+
syms = $2.split.map { |i| i =~ /'(.+?)'/ ? $1 : i.intern }
|
399
395
|
precs.push [dir, syms]
|
400
396
|
when /^%\}\s*$/
|
401
397
|
break
|
@@ -403,38 +399,41 @@ module Depager
|
|
403
399
|
error_exit "syntax error(prec).\n> #{line}"
|
404
400
|
end
|
405
401
|
end
|
406
|
-
|
402
|
+
precs
|
407
403
|
end
|
408
404
|
|
409
|
-
def parse_block
|
410
|
-
lineno
|
405
|
+
def parse_block(raw: false)
|
406
|
+
lineno = file.lineno
|
407
|
+
val = ""
|
411
408
|
until file.eof?
|
412
409
|
line = file.gets
|
413
|
-
break if
|
410
|
+
break if /^%\}/.match?(line)
|
411
|
+
|
414
412
|
val.concat line
|
415
413
|
end
|
416
414
|
return val if raw
|
417
415
|
|
418
|
-
delimiter =
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
416
|
+
delimiter = expanded_code_delimiter
|
417
|
+
<<~EXPANDED_CODE
|
418
|
+
module_eval <<'#{delimiter}', '#{file.path}', #{lineno + 1}
|
419
|
+
#{val}
|
420
|
+
#{delimiter}
|
421
|
+
EXPANDED_CODE
|
423
422
|
end
|
424
423
|
|
425
|
-
def parse_common
|
424
|
+
def parse_common(line)
|
426
425
|
case line
|
427
426
|
when /^\s*(#.*)?$/
|
428
|
-
#skip space and comment.
|
427
|
+
# skip space and comment.
|
429
428
|
when /^%decorate\s+(.*?)\s*\((.*)\)\s*$/
|
430
429
|
@decorators.push $1
|
431
430
|
@requirements.push $2
|
432
431
|
when /^%decorate\s+(.*?)\s*$/
|
433
432
|
@decorators.push $1
|
434
433
|
when /^%extend\s+(.*?)\s*\(\s*'(.*)'\s*\)\s*$/
|
435
|
-
@extensions.push [$2.strip, $1] unless @extensions.find{|i| i[1] == $1}
|
436
|
-
when /^%option\s+(\w+).(\w+)\s+(.*)\s*$/
|
437
|
-
if $1 ==
|
434
|
+
@extensions.push [$2.strip, $1] unless @extensions.find { |i| i[1] == $1 }
|
435
|
+
when /^%option\s+([\w:]+).(\w+)\s+(.*)\s*$/
|
436
|
+
if $1 == "Generator"
|
438
437
|
Depager.configuration[$2.to_sym] = $3
|
439
438
|
else
|
440
439
|
@options[$1] ||= []
|
@@ -451,6 +450,9 @@ module Depager
|
|
451
450
|
@precs = parse_prec
|
452
451
|
when /^%expanded_code_delimiter\s+(\S+)\s*$/
|
453
452
|
Depager.configuration[:expanded_code_delimiter] = $1
|
453
|
+
when /^%abort_behavior\s+(pending\s+)?(.*)$/
|
454
|
+
@inner_code << " def do_abort_driver; end\n" if $1
|
455
|
+
@inner_code << " def abort_driver; #{$2}; end\n" unless $2.strip.empty?
|
454
456
|
else
|
455
457
|
warning "syntax error(declaration).\n> #{line}"
|
456
458
|
end
|
@@ -458,63 +460,62 @@ module Depager
|
|
458
460
|
end
|
459
461
|
|
460
462
|
class ParserGenerator < Generator
|
461
|
-
def initialize d_parser
|
462
|
-
super
|
463
|
-
end
|
464
|
-
|
465
463
|
def parse
|
466
464
|
until file.eof?
|
467
465
|
line = file.gets
|
468
466
|
case line
|
469
467
|
when /^%%\s*$/
|
470
468
|
g_parser.parse(@d_parser.full_target_name, @precs, @extensions, @options)
|
471
|
-
@outer_code << parse_block(true)
|
469
|
+
@outer_code << parse_block(raw: true)
|
472
470
|
return generate_code parser_code_template
|
471
|
+
when /^%setup((\s*{\s*)|(\s.*))$/
|
472
|
+
@setup_code << ($2 ? parse_block : $3.lstrip)
|
473
473
|
else
|
474
474
|
parse_common(line)
|
475
475
|
end
|
476
476
|
end
|
477
|
-
|
477
|
+
nil
|
478
478
|
end
|
479
479
|
|
480
|
-
def parser_code_template
|
481
|
-
end
|
480
|
+
def parser_code_template; end
|
482
481
|
end
|
483
482
|
|
484
483
|
class ExtensionGenerator < Generator
|
485
484
|
attr_accessor :slaves
|
486
|
-
|
485
|
+
|
486
|
+
def initialize(d_parser)
|
487
487
|
super
|
488
|
-
@slaves = {
|
488
|
+
@slaves = {}
|
489
489
|
end
|
490
490
|
|
491
491
|
def parse
|
492
492
|
until file.eof?
|
493
493
|
line = file.gets
|
494
494
|
case line
|
495
|
-
when
|
496
|
-
hooks = $1.split
|
497
|
-
@banner = hooks.join(
|
495
|
+
when %r{^%hook\s+([\w \t]+?)(/((?:[^/\\]+|\\.)+)/(\s+skip)?)?\s*$}
|
496
|
+
hooks = $1.split
|
497
|
+
@banner = hooks.join(",")
|
498
498
|
@do_parse_re = $3
|
499
499
|
@do_parse_skip = $4
|
500
500
|
|
501
|
-
|
502
|
-
hooks.each do |i| i = i.to_sym
|
501
|
+
parts = hooks.map do |i|
|
503
502
|
error_exit "Unknown hook: #{i}" unless g_parser.hook_name? i
|
504
|
-
|
503
|
+
i.split("_").map(&:capitalize).join
|
505
504
|
end
|
505
|
+
target_name = "#{d_parser.target_namespace}::#{parts.join}#{slaves.size}::Parser"
|
506
|
+
@slaves[target_name] = hooks
|
506
507
|
@outer_code << parse_hook(target_name)
|
507
508
|
when /^%%\s*$/
|
508
|
-
@outer_code << parse_block(true)
|
509
|
+
@outer_code << parse_block(raw: true)
|
509
510
|
else
|
510
511
|
parse_common(line)
|
511
512
|
end
|
512
513
|
end
|
513
|
-
|
514
|
+
generate_code master_code_template
|
514
515
|
end
|
515
516
|
|
516
|
-
def parse_hook
|
517
|
-
inner =
|
517
|
+
def parse_hook(target_name)
|
518
|
+
inner = ""
|
518
519
|
precs = []
|
519
520
|
@slave_mixins = @mixins.dup
|
520
521
|
until file.eof?
|
@@ -539,11 +540,9 @@ module Depager
|
|
539
540
|
end
|
540
541
|
end
|
541
542
|
|
542
|
-
def slave_code_template
|
543
|
-
end
|
543
|
+
def slave_code_template; end
|
544
544
|
|
545
|
-
def master_code_template
|
546
|
-
end
|
545
|
+
def master_code_template; end
|
547
546
|
end
|
548
547
|
|
549
548
|
class Extension
|
@@ -552,31 +551,22 @@ module Depager
|
|
552
551
|
|
553
552
|
attr_reader :d_parser, :g_parser
|
554
553
|
|
555
|
-
def init_extension
|
556
|
-
end
|
554
|
+
def init_extension; end
|
557
555
|
|
558
|
-
def term_extension
|
559
|
-
end
|
556
|
+
def term_extension; end
|
560
557
|
|
561
|
-
def extension_registered
|
558
|
+
def extension_registered(g_parser)
|
562
559
|
@g_parser = g_parser
|
563
560
|
@d_parser = g_parser.d_parser
|
564
561
|
|
565
|
-
|
562
|
+
methods.sort.each do |m|
|
566
563
|
m = m.to_sym
|
567
564
|
g_parser.hooks[m].push [self, m] if g_parser.hook_name? m
|
568
565
|
end
|
569
566
|
end
|
570
567
|
|
571
568
|
def decorator_name
|
572
|
-
self.class.name.split(
|
569
|
+
self.class.name.split("::").last.sub(/Extension$/, "")
|
573
570
|
end
|
574
571
|
end
|
575
572
|
end
|
576
|
-
|
577
|
-
class String
|
578
|
-
def unindent
|
579
|
-
indent = match(/\n(\s+)/) ? $1 : ''
|
580
|
-
gsub(/^#{indent}/m, '')
|
581
|
-
end
|
582
|
-
end
|