rex 0.0.4 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/CHANGELOG.rdoc +7 -0
  2. data/DOCUMENTATION.en.rdoc +215 -0
  3. data/DOCUMENTATION.ja.rdoc +205 -0
  4. data/Manifest.txt +37 -0
  5. data/README.ja +73 -0
  6. data/README.rdoc +53 -0
  7. data/Rakefile +28 -0
  8. data/bin/rex +18 -0
  9. data/lib/rex.rb +3 -23
  10. data/lib/rex/generator.rb +523 -0
  11. data/lib/rex/info.rb +16 -0
  12. data/lib/rex/rexcmd.rb +136 -0
  13. data/sample/a.cmd +1 -0
  14. data/sample/b.cmd +1 -0
  15. data/sample/c.cmd +4 -0
  16. data/sample/calc3.racc +47 -0
  17. data/sample/calc3.rex +15 -0
  18. data/sample/calc3.rex.rb +94 -0
  19. data/sample/calc3.tab.rb +188 -0
  20. data/sample/error1.rex +15 -0
  21. data/sample/error2.rex +15 -0
  22. data/sample/sample.html +32 -0
  23. data/sample/sample.rex +15 -0
  24. data/sample/sample.rex.rb +100 -0
  25. data/sample/sample.xhtml +32 -0
  26. data/sample/sample1.c +9 -0
  27. data/sample/sample1.rex +43 -0
  28. data/sample/sample2.bas +4 -0
  29. data/sample/sample2.rex +33 -0
  30. data/sample/simple.html +7 -0
  31. data/sample/simple.xhtml +10 -0
  32. data/sample/xhtmlparser.racc +66 -0
  33. data/sample/xhtmlparser.rex +72 -0
  34. data/test/assets/test.rex +12 -0
  35. data/test/rex-20060125.rb +152 -0
  36. data/test/rex-20060511.rb +143 -0
  37. data/test/test_generator.rb +184 -0
  38. metadata +74 -57
  39. data/README +0 -50
  40. data/lib/rex/array.rb +0 -13
  41. data/lib/rex/kernel.rb +0 -11
  42. data/lib/rex/modules/boolean.rb +0 -14
  43. data/lib/rex/modules/caller_name.rb +0 -15
  44. data/lib/rex/modules/ordinal.rb +0 -35
  45. data/lib/rex/modules/propercase.rb +0 -15
  46. data/lib/rex/modules/roman.rb +0 -41
  47. data/lib/rex/modules/scrub.rb +0 -66
  48. data/lib/rex/modules/stacktrace.rb +0 -31
  49. data/lib/rex/modules/swap.rb +0 -13
  50. data/lib/rex/modules/to_proc.rb +0 -13
  51. data/lib/rex/modules/tuple.rb +0 -14
  52. data/lib/rex/modules/wrap.rb +0 -15
  53. data/lib/rex/numeric.rb +0 -19
  54. data/lib/rex/string.rb +0 -21
  55. data/lib/rex/symbol.rb +0 -13
  56. data/test/boolean.rb +0 -64
  57. data/test/caller_name.rb +0 -26
  58. data/test/ordinal.rb +0 -609
  59. data/test/propercase.rb +0 -40
  60. data/test/roman.rb +0 -335
  61. data/test/scrub.rb +0 -27
  62. data/test/stacktrace.rb +0 -24
  63. data/test/swap.rb +0 -44
  64. data/test/to_proc.rb +0 -24
  65. data/test/tuple.rb +0 -26
  66. data/test/wrap.rb +0 -44
@@ -0,0 +1,73 @@
1
+ Rex README
2
+ ===========
3
+
4
+ Rex �� Ruby �Τ���Υ�����ʥ����ͥ졼���Ǥ���
5
+ lex �� Ruby �Ǥ��������ޤ���
6
+ Racc �ȤȤ�˻Ȥ��褦���߷פ���Ƥ��ޤ���
7
+
8
+
9
+ ɬ�״Ķ�
10
+ --------
11
+
12
+ * ruby 1.8 �ʹ�
13
+
14
+
15
+ ���󥹥ȡ���
16
+ ------------
17
+
18
+ �ѥå������Υȥåץǥ��쥯�ȥ�Ǽ��Τ褦�����Ϥ��Ƥ���������
19
+ ($ ���̾�桼����# �ϥ롼�ȤΥץ���ץȤǤ�)
20
+
21
+ $ ruby setup.rb config
22
+ $ ruby setup.rb setup
23
+ ($ su)
24
+ # ruby setup.rb install
25
+
26
+ ������̾�Υѥ��� Racc �����󥹥ȡ��뤵��ޤ�����ʬ�ι���
27
+ �ʥǥ��쥯�ȥ�˥��󥹥ȡ��뤷�����Ȥ��ϡ�setup.rb config ��
28
+ �Ƽ索�ץ�����Ĥ��Ƽ¹Ԥ��Ƥ������������ץ����Υꥹ�Ȥ�
29
+
30
+ $ ruby setup.rb --help
31
+
32
+ �Ǹ����ޤ���
33
+
34
+
35
+ �ƥ���
36
+ ------
37
+
38
+ sample/ �ʲ��ˤ����Ĥ� Rex ��ʸˡ�ե�����Υ���ץ뤬�Ѱ�
39
+ ���Ƥ���ޤ����ʲ���¹Ԥ��Ƥ���������
40
+
41
+ $ rex sample1.rex --stub
42
+ $ ruby sample1.rex.rb sample1.c
43
+
44
+ $ rex sample2.rex --stub
45
+ $ ruby sample2.rex.rb sample2.bas
46
+
47
+ $ racc calc3.racc
48
+ $ rex calc3.rex
49
+ $ ruby calc3.tab.rb
50
+
51
+ Rex �ξܤ���ʸˡ�� doc/ �ǥ��쥯�ȥ�ʲ��򸫤Ƥ���������
52
+ �ޤ�������� sample/ �ǥ��쥯�ȥ�ʲ��򸫤Ƥ���������
53
+
54
+
55
+ �饤����
56
+ ----------
57
+
58
+ �饤���󥹤� GNU Lesser General Public License (LGPL) version 2
59
+ �Ǥ����������桼�����񤤤���§�ե�����䡢Racc ������������������
60
+ Ruby ������ץȤϤ����оݳ��Ǥ��������ʥ饤���󥹤����ۤ��Ƥ���������
61
+
62
+
63
+ �Х��ʤ�
64
+ --------
65
+
66
+ Rex ��ȤäƤ��ƥХ��餷�����ݤ����������顢�����Υ��ɥ쥹�ޤ�
67
+ �᡼��򤯤�������
68
+ ���ΤȤ��ϤǤ�������Х���Ƹ��Ǥ���ʸˡ�ե�������դ��Ƥ���������
69
+
70
+
71
+ ARIMA Yasuhiro
72
+ arima.yasuhiro@nifty.com
73
+ http://raa.ruby-lang.org/project/rex/
@@ -0,0 +1,53 @@
1
+ = Rex
2
+
3
+ * http://rex.rubyforge.org
4
+ * http://github.com/aaronp/rex/tree/master
5
+
6
+ == DESCRIPTION
7
+
8
+ Rex is a lexical scanner generator.
9
+ It is written in Ruby itself, and generates Ruby program.
10
+ It is designed for use with Racc.
11
+
12
+
13
+ == SYNOPSIS
14
+
15
+ Here is a sample lexical definition:
16
+
17
+ class Sample
18
+ macro
19
+ BLANK [\ \t]+
20
+ rule
21
+ BLANK # no action
22
+ \d+ { [:digit, text.to_i] }
23
+ \w+ { [:word, text] }
24
+ \n
25
+ . { [text, text] }
26
+ end
27
+
28
+ Here is the command line usage:
29
+
30
+ $ rex sample1.rex --stub
31
+ $ ruby sample1.rex.rb sample1.c
32
+
33
+ $ rex sample2.rex --stub
34
+ $ ruby sample2.rex.rb sample2.bas
35
+
36
+ $ racc calc3.racc
37
+ $ rex calc3.rex
38
+ $ ruby calc3.tab.rb
39
+
40
+ == REQUIREMENTS
41
+
42
+ * ruby version 1.8.x or later.
43
+
44
+ == INSTALL
45
+
46
+ * sudo gem install rex
47
+
48
+ == LICENSE
49
+
50
+ Rex is distributed under the terms of the GNU Lesser General
51
+ Public License version 2. Note that you do NOT need to follow
52
+ LGPL for your own parser (Rex outputs). You can provide those
53
+ files under any licenses you want.
@@ -0,0 +1,28 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
7
+ require 'rex'
8
+
9
+ HOE = Hoe.new('rex', Rex::VERSION) do |p|
10
+ p.readme_file = 'README.rdoc'
11
+ p.history_file = 'CHANGELOG.rdoc'
12
+ p.developer('Aaron Patterson', 'aaronp@rubyforge.org')
13
+ p.extra_rdoc_files = FileList['*.rdoc']
14
+ p.rubyforge_name = 'ruby-rex'
15
+ end
16
+
17
+ namespace :gem do
18
+ namespace :spec do
19
+ task :dev do
20
+ File.open("#{HOE.name}.gemspec", 'w') do |f|
21
+ HOE.spec.version = "#{HOE.version}.#{Time.now.strftime("%Y%m%d%H%M%S")}"
22
+ f.write(HOE.spec.to_ruby)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ # vim: syntax=Ruby
data/bin/rex ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # rex
4
+ #
5
+ # Copyright (c) 2005-2006 ARIMA Yasuhiro <arima.yasuhiro@nifty.com>
6
+ #
7
+ # This program is free software.
8
+ # You can distribute/modify this program under the terms of
9
+ # the GNU LGPL, Lesser General Public License version 2.1.
10
+ # For details of LGPL, see the file "COPYING".
11
+ #
12
+
13
+ ## ---------------------------------------------------------------------
14
+
15
+ require 'rubygems'
16
+ require 'rex'
17
+
18
+ Rex::Cmd.new.run
data/lib/rex.rb CHANGED
@@ -1,23 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
- # rex.rb
4
- # yesmar@speakeasy.net
5
-
6
- module REX
7
- REX::NAME = 'rex'
8
- REX::VERSION = '0.0.4'
9
- REX::COPYRIGHT = 'Copyright (c) 2008 Ramsey Dow'
10
- def self.copyright() REX::COPYRIGHT end
11
- def self.version() REX::VERSION end
12
- def self.libdir() File.expand_path(__FILE__).gsub(%r/\.rb$/, '') end
13
- end
14
-
15
- $LOAD_PATH.unshift(File.dirname(__FILE__)+'/rex')
16
-
17
- require 'array'
18
- require 'kernel'
19
- require 'numeric'
20
- require 'string'
21
- require 'symbol'
22
-
23
- raise RuntimeError, 'This library is for require only' if $0 == __FILE__
1
+ require 'rex/generator'
2
+ require 'rex/info'
3
+ require 'rex/rexcmd'
@@ -0,0 +1,523 @@
1
+ #
2
+ # generator.rb
3
+ #
4
+ # Copyright (c) 2005-2006 ARIMA Yasuhiro <arima.yasuhiro@nifty.com>
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2 or later.
9
+ #
10
+
11
+ require 'strscan'
12
+ module Rex
13
+
14
+ ## ---------------------------------------------------------------------
15
+ class ParseError < StandardError ; end
16
+
17
+ ## ---------------------------------------------------------------------
18
+ class Generator
19
+
20
+ ## ---------------------------------------------------------------------
21
+ attr_accessor :grammar_file
22
+ attr_accessor :grammar_lines
23
+ attr_accessor :scanner_file
24
+ attr_accessor :module_name
25
+ attr_accessor :class_name
26
+ attr_accessor :lineno
27
+ attr_accessor :rules
28
+ attr_accessor :exclusive_states
29
+ attr_accessor :ignorecase
30
+ attr_accessor :independent
31
+ attr_accessor :debug
32
+
33
+ ## ---------------------------------------------------------------------
34
+ def initialize(opts)
35
+ @lineno = 0
36
+ @macro = {}
37
+ @rules = []
38
+ @exclusive_states = [nil]
39
+ @grammar_lines = nil
40
+ @scanner_header = ""
41
+ @scanner_footer = ""
42
+ @scanner_inner = ""
43
+ @opt = opts
44
+ end
45
+
46
+ ## ---------------------------------------------------------------------
47
+ def add_header( st )
48
+ @scanner_header += "#{st}\n"
49
+ end
50
+
51
+ ## ---------------------------------------------------------------------
52
+ def add_footer( st )
53
+ @scanner_footer += "#{st}\n"
54
+ end
55
+
56
+ ## ---------------------------------------------------------------------
57
+ def add_inner( st )
58
+ @scanner_inner += "#{st}\n"
59
+ end
60
+
61
+ ## ---------------------------------------------------------------------
62
+ def add_option( st )
63
+ opts = st.split
64
+ opts.each do |opt|
65
+ case opt
66
+ when /ignorecase/i
67
+ @opt['--ignorecase'] = true
68
+ when /stub/i
69
+ @opt['--stub'] = true
70
+ when /independent/i
71
+ @opt['--independent'] = true
72
+ end
73
+ end
74
+ end
75
+
76
+ ## ---------------------------------------------------------------------
77
+ def add_macro( st )
78
+ ss = StringScanner.new(st)
79
+ ss.scan(/\s+/)
80
+ key = ss.scan(/\S+/)
81
+ ss.scan(/\s+/)
82
+ st = ss.post_match
83
+ len = st.size
84
+ ndx = 0
85
+ while ndx <= len
86
+ c = st[ndx,1]
87
+ ndx += 1
88
+ case c
89
+ when '\\'
90
+ ndx += 1
91
+ next
92
+ when '#', ' '
93
+ ndx -= 1
94
+ break
95
+ end
96
+ end
97
+ expr = st[0,ndx]
98
+ key = '{' + key + '}'
99
+ @macro.each_pair do |k, e|
100
+ expr.gsub!(k) { |m| e }
101
+ end
102
+ @macro[key] = expr
103
+ rescue
104
+ raise ParseError, "parse error in add_macro:'#{st}'"
105
+ end
106
+
107
+ ## ---------------------------------------------------------------------
108
+ def add_rule( rule_state, rule_expr, rule_action=nil )
109
+ st = rule_expr.dup
110
+ @macro.each_pair do |k, e|
111
+ rule_expr.gsub!(k) { |m| e }
112
+ end
113
+ if rule_state.to_s[1,1] =~ /[A-Z]/
114
+ @exclusive_states << rule_state unless @exclusive_states.include?(rule_state)
115
+ exclusive_state = rule_state
116
+ start_state = nil
117
+ else
118
+ exclusive_state = nil
119
+ start_state = rule_state
120
+ end
121
+ rule = [exclusive_state, start_state, rule_expr, rule_action]
122
+ @rules << rule
123
+ rescue
124
+ raise ParseError, "parse error in add_rule:'#{st}'"
125
+ end
126
+
127
+ def read_grammar
128
+ @grammar_lines = StringScanner.new File.read(grammar_file)
129
+ end
130
+
131
+ def next_line
132
+ @lineno += 1
133
+ @grammar_lines.scan_until(/\n/).chomp
134
+ rescue
135
+ nil
136
+ end
137
+
138
+ def parse
139
+ state1 = :HEAD
140
+ state2 = nil
141
+ state3 = nil
142
+ lastmodes = []
143
+ while st = next_line
144
+ case state1
145
+ when :FOOT
146
+ add_footer st
147
+
148
+ when :HEAD
149
+ ss = StringScanner.new(st)
150
+ if ss.scan(/class/)
151
+ state1 = :CLASS
152
+ st = ss.post_match.strip
153
+ if st =~ /^(\S+)::(\S+)/
154
+ @module_name = $1
155
+ @class_name = $2
156
+ else
157
+ @module_name = nil
158
+ @class_name = st
159
+ end
160
+ else
161
+ add_header st
162
+ end
163
+
164
+ when :CLASS
165
+ s = st.strip
166
+ next if s.size == 0 or s[0,1] == '#'
167
+
168
+ ss = StringScanner.new(st)
169
+ if ss.scan(/option.*$/)
170
+ state2 = :OPTION
171
+ next
172
+ end
173
+ if ss.scan(/inner.*$/)
174
+ state2 = :INNER
175
+ next
176
+ end
177
+ if ss.scan(/macro.*$/)
178
+ state2 = :MACRO
179
+ next
180
+ end
181
+ if ss.scan(/rule.*$/)
182
+ state2 = :RULE
183
+ next
184
+ end
185
+ if ss.scan(/end.*$/)
186
+ state1 = :FOOT
187
+ next
188
+ end
189
+
190
+ case state2
191
+ when :OPTION
192
+ add_option st
193
+
194
+ when :INNER
195
+ add_inner st
196
+
197
+ when :MACRO
198
+ add_macro st
199
+
200
+ when :RULE
201
+ case state3
202
+ when nil
203
+ rule_state, rule_expr, rule_action = parse_rule(st)
204
+ if rule_action =~ /\s*\{/
205
+ lastmodes = parse_action(rule_action, lastmodes)
206
+ if lastmodes.empty?
207
+ add_rule rule_state, rule_expr, rule_action
208
+ else
209
+ state3 = :CONT
210
+ rule_action += "\n"
211
+ end
212
+ else
213
+ add_rule rule_state, rule_expr
214
+ end
215
+
216
+ when :CONT
217
+ rule_action += "#{st}\n"
218
+ lastmodes = parse_action(st, lastmodes)
219
+ if lastmodes.empty?
220
+ state3 = nil
221
+ add_rule rule_state, rule_expr, rule_action
222
+ else
223
+ end
224
+
225
+ end # case state3
226
+
227
+ end # case state2
228
+
229
+ end # case state1
230
+
231
+ end # while
232
+
233
+ end
234
+
235
+ ## ---------------------------------------------------------------------
236
+ def parse_rule(st)
237
+ st.strip!
238
+ return if st.size == 0 or st[0,1] == '#'
239
+ ss = StringScanner.new(st)
240
+ ss.scan(/\s+/)
241
+ rule_state = ss.scan(/\:\S+/)
242
+ ss.scan(/\s+/)
243
+ rule_expr = ss.scan(/\S+/)
244
+ ss.scan(/\s+/)
245
+ [rule_state, rule_expr, ss.post_match]
246
+ end
247
+
248
+ ## ---------------------------------------------------------------------
249
+ def parse_action(st, lastmodes=[])
250
+ modes = lastmodes
251
+ mode = lastmodes[-1]
252
+ ss = StringScanner.new(st)
253
+ until ss.eos?
254
+ c = ss.scan(/./)
255
+ case c
256
+ when '#'
257
+ if (mode == :brace) or (mode == nil)
258
+ #p [c, mode, modes]
259
+ return modes
260
+ end
261
+ when '{'
262
+ if (mode == :brace) or (mode == nil)
263
+ mode = :brace
264
+ modes.push mode
265
+ end
266
+ when '}'
267
+ if (mode == :brace)
268
+ modes.pop
269
+ mode = modes[0]
270
+ end
271
+ when "'"
272
+ if (mode == :brace)
273
+ mode = :quote
274
+ modes.push mode
275
+ elsif (mode == :quote)
276
+ modes.pop
277
+ mode = modes[0]
278
+ end
279
+ when '"'
280
+ if (mode == :brace)
281
+ mode = :doublequote
282
+ modes.push mode
283
+ elsif (mode == :doublequote)
284
+ modes.pop
285
+ mode = modes[0]
286
+ end
287
+ when '`'
288
+ if (mode == :brace)
289
+ mode = :backquote
290
+ modes.push mode
291
+ elsif (mode == :backquote)
292
+ modes.pop
293
+ mode = modes[0]
294
+ end
295
+ end
296
+ end
297
+ #p [c, mode, modes]
298
+ return modes
299
+ end
300
+
301
+ ## ---------------------------------------------------------------------
302
+
303
+ REX_HEADER = <<-REX_EOT
304
+ #--
305
+ # DO NOT MODIFY!!!!
306
+ # This file is automatically generated by rex %s
307
+ # from lexical definition file "%s".
308
+ #++
309
+
310
+ REX_EOT
311
+
312
+ REX_UTIL = <<-REX_EOT
313
+ require 'strscan'
314
+
315
+ class ScanError < StandardError ; end
316
+
317
+ attr_reader :lineno
318
+ attr_reader :filename
319
+
320
+ def scan_setup ; end
321
+
322
+ def action &block
323
+ yield
324
+ end
325
+
326
+ def scan_str( str )
327
+ scan_evaluate str
328
+ do_parse
329
+ end
330
+
331
+ def load_file( filename )
332
+ @filename = filename
333
+ open(filename, "r") do |f|
334
+ scan_evaluate f.read
335
+ end
336
+ end
337
+
338
+ def scan_file( filename )
339
+ load_file filename
340
+ do_parse
341
+ end
342
+
343
+ REX_EOT
344
+
345
+ REX_NEXTTOKEN_DEBUG = <<-REX_EOT
346
+ def next_token
347
+ p token = @rex_tokens.shift
348
+ token
349
+ end
350
+ REX_EOT
351
+
352
+ REX_NEXTTOKEN = <<-REX_EOT
353
+ def next_token
354
+ @rex_tokens.shift
355
+ end
356
+ REX_EOT
357
+
358
+ REX_STUB = <<-REX_EOT
359
+
360
+ if __FILE__ == $0
361
+ exit if ARGV.size != 1
362
+ filename = ARGV.shift
363
+ rex = %s.new
364
+ begin
365
+ rex.load_file filename
366
+ while token = rex.next_token
367
+ p token
368
+ end
369
+ rescue
370
+ $stderr.printf %s, rex.filename, rex.lineno, $!.message
371
+ end
372
+ end
373
+ REX_EOT
374
+
375
+ ## ---------------------------------------------------------------------
376
+
377
+
378
+ def scanner_io
379
+ unless scanner_file = @opt['--output-file']
380
+ scanner_file = grammar_file + ".rb"
381
+ end
382
+ f = File.open(scanner_file, 'w')
383
+ end
384
+ private :scanner_io
385
+
386
+ def write_scanner f = scanner_io
387
+ ## scan flag
388
+ flag = ""
389
+ flag += "i" if @opt['--ignorecase']
390
+ ## header
391
+ f.printf REX_HEADER, Rex::VERSION, grammar_file
392
+
393
+ unless @opt['--independent']
394
+ f.printf "require 'racc/parser'\n"
395
+ end
396
+
397
+ @scanner_header.each_line do |s|
398
+ f.print s
399
+ end
400
+ if @module_name
401
+ f.puts "module #{@module_name}"
402
+ end
403
+ if @opt['--independent']
404
+ f.puts "class #{@class_name}"
405
+ else
406
+ f.puts "class #{@class_name} < Racc::Parser"
407
+ end
408
+
409
+ ## utility method
410
+ f.print REX_UTIL
411
+
412
+ if @opt['--debug']
413
+ f.print REX_NEXTTOKEN_DEBUG
414
+ else
415
+ f.print REX_NEXTTOKEN
416
+ end
417
+
418
+ ## scanner method
419
+
420
+ f.print <<-REX_EOT
421
+
422
+ def scan_evaluate( str )
423
+ scan_setup
424
+ @rex_tokens = []
425
+ @lineno = 1
426
+ ss = StringScanner.new(str)
427
+ state = nil
428
+ until ss.eos?
429
+ text = ss.peek(1)
430
+ @lineno += 1 if text == "\\n"
431
+ case state
432
+ REX_EOT
433
+
434
+ exclusive_states.each do |es|
435
+ f.printf <<-REX_EOT
436
+ when #{es ? es.to_s : "nil"}
437
+ case
438
+ REX_EOT
439
+ rules.each do |rule|
440
+ exclusive_state, start_state, rule_expr, rule_action = *rule
441
+ if es == exclusive_state
442
+
443
+ if rule_action
444
+ if start_state
445
+ f.print <<-REX_EOT
446
+ when (state == #{start_state}) and (text = ss.scan(/#{rule_expr}/#{flag}))
447
+ @rex_tokens.push action #{rule_action}
448
+
449
+ REX_EOT
450
+ else
451
+ f.print <<-REX_EOT
452
+ when (text = ss.scan(/#{rule_expr}/#{flag}))
453
+ @rex_tokens.push action #{rule_action}
454
+
455
+ REX_EOT
456
+ end
457
+ else
458
+ if start_state
459
+ f.print <<-REX_EOT
460
+ when (state == #{start_state}) and (text = ss.scan(/#{rule_expr}/#{flag}))
461
+ ;
462
+
463
+ REX_EOT
464
+ else
465
+ f.print <<-REX_EOT
466
+ when (text = ss.scan(/#{rule_expr}/#{flag}))
467
+ ;
468
+
469
+ REX_EOT
470
+ end
471
+ end
472
+
473
+ end
474
+ end
475
+ f.print <<-REX_EOT
476
+ else
477
+ text = ss.string[ss.pos .. -1]
478
+ raise ScanError, "can not match: '" + text + "'"
479
+ end # if
480
+
481
+ REX_EOT
482
+ end
483
+ f.print <<-REX_EOT
484
+ else
485
+ raise ScanError, "undefined state: '" + state.to_s + "'"
486
+ end # case state
487
+ end # until ss
488
+ end # def scan_evaluate
489
+
490
+ REX_EOT
491
+
492
+ ## inner method
493
+ @scanner_inner.each_line do |s|
494
+ f.print s
495
+ end
496
+ f.puts "end # class"
497
+ f.puts "end # module" if @module_name
498
+
499
+ ## footer
500
+ @scanner_footer.each_line do |s|
501
+ f.print s
502
+ end # case
503
+
504
+ ## stub main
505
+ f.printf REX_STUB, @class_name, '"%s:%d:%s\n"' if @opt['--stub']
506
+ f.close
507
+
508
+ end ## def
509
+ end ## class
510
+ end ## module
511
+
512
+
513
+ ## ---------------------------------------------------------------------
514
+ ## test
515
+
516
+ if __FILE__ == $0
517
+ rex = Rex::Generator.new(nil)
518
+ rex.grammar_file = "sample.rex"
519
+ rex.read_grammar
520
+ rex.parse
521
+ rex.write_scanner
522
+ end
523
+