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,12 @@
1
+ module A
2
+ module B
3
+ class C < SomethingElse
4
+
5
+ macro
6
+ w [\s\r\n\f]*
7
+
8
+ # [:state] pattern [actions]
9
+
10
+ {w}~={w} { [:INCLUDES, text] }
11
+
12
+ end
@@ -0,0 +1,152 @@
1
+ #!C:/Program Files/ruby-1.8/bin/ruby
2
+ #
3
+ # rex
4
+ #
5
+ # Copyright (c) 2005 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
+ REX_OPTIONS = <<-EOT
16
+
17
+ o -o --output-file <outfile> file name of output [<filename>.rb]
18
+ o -s --stub - append stub code for debug
19
+ o -i --ignorecase - ignore char case
20
+ o -C --check-only - syntax check only
21
+ o - --independent - independent mode
22
+ o -d --debug - print debug information
23
+ o -h --help - print this message and quit
24
+ o - --version - print version and quit
25
+ o - --copyright - print copyright and quit
26
+
27
+ EOT
28
+
29
+ ## ---------------------------------------------------------------------
30
+
31
+ require 'getoptlong'
32
+ require 'rex/generator'
33
+ require 'rex/info'
34
+
35
+ ## ---------------------------------------------------------------------
36
+
37
+ =begin
38
+ class Rex
39
+ def initialize
40
+ end
41
+ end
42
+ =end
43
+
44
+ def main
45
+ $cmd = File.basename($0, ".rb")
46
+ opt = get_options
47
+ filename = ARGV[0]
48
+
49
+ rex = Rex::Generator.new(opt)
50
+ begin
51
+ rex.grammar_file = filename
52
+ rex.read_grammar
53
+ rex.parse
54
+ if opt['--check-only']
55
+ $stderr.puts "syntax ok"
56
+ return 0
57
+ end
58
+ rex.write_scanner
59
+
60
+ rescue Rex::ParseError, Errno::ENOENT
61
+ msg = $!.to_s
62
+ unless /\A\d/ === msg
63
+ msg[0,0] = ' '
64
+ end
65
+ $stderr.puts "#{$cmd}:#{rex.grammar_file}:#{rex.lineno}:#{msg}"
66
+ return 1
67
+
68
+ end
69
+ return 0
70
+ end
71
+
72
+ ## ---------------------------------------------------------------------
73
+ def get_options
74
+ tmp = REX_OPTIONS.collect do |line|
75
+ next if /\A\s*\z/ === line
76
+ disp, sopt, lopt, takearg, doc = line.strip.split(/\s+/, 5)
77
+ a = []
78
+ a.push lopt unless lopt == '-'
79
+ a.push sopt unless sopt == '-'
80
+ a.push takearg == '-' ?
81
+ GetoptLong::NO_ARGUMENT : GetoptLong::REQUIRED_ARGUMENT
82
+ a
83
+ end
84
+ getopt = GetoptLong.new(*tmp.compact)
85
+ getopt.quiet = true
86
+
87
+ opt = {}
88
+ begin
89
+ getopt.each do |name, arg|
90
+ raise GetoptLong::InvalidOption,
91
+ "#{$cmd}: #{name} given twice" if opt.key? name
92
+ opt[name] = arg.empty? ? true : arg
93
+ end
94
+ rescue GetoptLong::AmbigousOption, GetoptLong::InvalidOption,
95
+ GetoptLong::MissingArgument, GetoptLong::NeedlessArgument
96
+ usage 1, $!.message
97
+ end
98
+
99
+ usage if opt['--help']
100
+
101
+ if opt['--version']
102
+ puts "#{$cmd} version #{Rex::Version}"
103
+ exit 0
104
+ end
105
+ if opt['--copyright']
106
+ puts "#{$cmd} version #{Rex::Version}"
107
+ puts "#{Rex::Copyright} <#{Rex::Mailto}>"
108
+ exit 0
109
+ end
110
+
111
+ usage(1, 'no grammar file given') if ARGV.empty?
112
+ usage(1, 'too many grammar files given') if ARGV.size > 1
113
+
114
+ opt
115
+ end
116
+
117
+ ## ---------------------------------------------------------------------
118
+
119
+ def usage(status=0, msg=nil )
120
+ f = (status == 0 ? $stdout : $stderr)
121
+ f.puts "#{$cmd}: #{msg}" if msg
122
+ f.print <<-EOT
123
+ Usage: #{$cmd} [options] <grammar file>
124
+ Options:
125
+ EOT
126
+
127
+ REX_OPTIONS.each do |line|
128
+ next if line.strip.empty?
129
+ if /\A\s*\z/ === line
130
+ f.puts
131
+ next
132
+ end
133
+
134
+ disp, sopt, lopt, takearg, doc = line.strip.split(/\s+/, 5)
135
+ if disp == 'o'
136
+ sopt = nil if sopt == '-'
137
+ lopt = nil if lopt == '-'
138
+ opt = [sopt, lopt].compact.join(',')
139
+
140
+ takearg = nil if takearg == '-'
141
+ opt = [opt, takearg].compact.join(' ')
142
+
143
+ f.printf "%-27s %s\n", opt, doc
144
+ end
145
+ end
146
+
147
+ exit status
148
+ end
149
+
150
+ ## ---------------------------------------------------------------------
151
+
152
+ main
@@ -0,0 +1,143 @@
1
+ #!/usr/local/bin/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
+ REX_OPTIONS = <<-EOT
16
+
17
+ o -o --output-file <outfile> file name of output [<filename>.rb]
18
+ o -s --stub - append stub code for debug
19
+ o -i --ignorecase - ignore char case
20
+ o -C --check-only - syntax check only
21
+ o - --independent - independent mode
22
+ o -d --debug - print debug information
23
+ o -h --help - print this message and quit
24
+ o - --version - print version and quit
25
+ o - --copyright - print copyright and quit
26
+
27
+ EOT
28
+
29
+ ## ---------------------------------------------------------------------
30
+
31
+ require 'getoptlong'
32
+ require 'rex/generator'
33
+ require 'rex/info'
34
+
35
+ ## ---------------------------------------------------------------------
36
+
37
+ class RexRunner
38
+ def run
39
+ @status = 1
40
+ usage 'no grammar file given' if ARGV.empty?
41
+ usage 'too many grammar files given' if ARGV.size > 1
42
+ filename = ARGV[0]
43
+
44
+ rex = Rex::Generator.new(@opt)
45
+ begin
46
+ rex.grammar_file = filename
47
+ rex.read_grammar
48
+ rex.parse
49
+ if @opt['--check-only']
50
+ $stderr.puts "syntax ok"
51
+ return 0
52
+ end
53
+ rex.write_scanner
54
+ @status = 0
55
+
56
+ rescue Rex::ParseError, Errno::ENOENT
57
+ msg = $!.to_s
58
+ unless /\A\d/ === msg
59
+ msg[0,0] = ' '
60
+ end
61
+ $stderr.puts "#{@cmd}:#{rex.grammar_file}:#{rex.lineno}:#{msg}"
62
+
63
+ ensure
64
+ exit @status
65
+
66
+ end
67
+ end
68
+
69
+ def initialize
70
+ @status = 2
71
+ @cmd = File.basename($0, ".rb")
72
+ tmp = REX_OPTIONS.collect do |line|
73
+ next if /\A\s*\z/ === line
74
+ disp, sopt, lopt, takearg, doc = line.strip.split(/\s+/, 5)
75
+ a = []
76
+ a.push lopt unless lopt == '-'
77
+ a.push sopt unless sopt == '-'
78
+ a.push takearg == '-' ?
79
+ GetoptLong::NO_ARGUMENT : GetoptLong::REQUIRED_ARGUMENT
80
+ a
81
+ end
82
+ getopt = GetoptLong.new(*tmp.compact)
83
+ getopt.quiet = true
84
+
85
+ @opt = {}
86
+ begin
87
+ getopt.each do |name, arg|
88
+ raise GetoptLong::InvalidOption,
89
+ "#{@cmd}: #{name} given twice" if @opt.key? name
90
+ @opt[name] = arg.empty? ? true : arg
91
+ end
92
+ rescue GetoptLong::AmbigousOption, GetoptLong::InvalidOption,
93
+ GetoptLong::MissingArgument, GetoptLong::NeedlessArgument
94
+ usage $!.message
95
+ end
96
+
97
+ usage if @opt['--help']
98
+
99
+ if @opt['--version']
100
+ puts "#{@cmd} version #{Rex::Version}"
101
+ exit 0
102
+ end
103
+ if @opt['--copyright']
104
+ puts "#{@cmd} version #{Rex::Version}"
105
+ puts "#{Rex::Copyright} <#{Rex::Mailto}>"
106
+ exit 0
107
+ end
108
+ end
109
+
110
+ def usage( msg=nil )
111
+ f = $stderr
112
+ f.puts "#{@cmd}: #{msg}" if msg
113
+ f.print <<-EOT
114
+ Usage: #{@cmd} [options] <grammar file>
115
+ Options:
116
+ EOT
117
+
118
+ REX_OPTIONS.each do |line|
119
+ next if line.strip.empty?
120
+ if /\A\s*\z/ === line
121
+ f.puts
122
+ next
123
+ end
124
+
125
+ disp, sopt, lopt, takearg, doc = line.strip.split(/\s+/, 5)
126
+ if disp == 'o'
127
+ sopt = nil if sopt == '-'
128
+ lopt = nil if lopt == '-'
129
+ opt = [sopt, lopt].compact.join(',')
130
+
131
+ takearg = nil if takearg == '-'
132
+ opt = [opt, takearg].compact.join(' ')
133
+
134
+ f.printf "%-27s %s\n", opt, doc
135
+ end
136
+ end
137
+
138
+ exit @status
139
+ end
140
+ end
141
+
142
+ RexRunner.new.run
143
+
@@ -0,0 +1,184 @@
1
+ require 'test/unit'
2
+ require 'tempfile'
3
+ require 'rex'
4
+ require 'stringio'
5
+
6
+ class TestGenerator < Test::Unit::TestCase
7
+ def test_header_is_written_after_module
8
+ rex = Rex::Generator.new(
9
+ "--independent" => true
10
+ )
11
+ rex.grammar_file = File.join File.dirname(__FILE__), 'assets', 'test.rex'
12
+ rex.read_grammar
13
+ rex.parse
14
+
15
+ output = StringIO.new
16
+ rex.write_scanner output
17
+
18
+ comments = []
19
+ output.string.split(/[\n]/).each do |line|
20
+ comments << line.chomp if line =~ /^#/
21
+ end
22
+
23
+ assert_match 'DO NOT MODIFY', comments.join
24
+ assert_equal '#--', comments.first
25
+ assert_equal '#++', comments.last
26
+ end
27
+
28
+ def test_read_non_existent_file
29
+ rex = Rex::Generator.new(nil)
30
+ rex.grammar_file = 'non_existent_file'
31
+ assert_raises Errno::ENOENT do
32
+ rex.read_grammar
33
+ end
34
+ end
35
+
36
+ def test_scanner_inherits
37
+ rex = Rex::Generator.new(
38
+ "--independent" => true
39
+ )
40
+ rex.grammar_lines = StringScanner.new %q{
41
+ class Calculator < Bar
42
+ rule
43
+ \d+ { [:NUMBER, text.to_i] }
44
+ \s+ { [:S, text] }
45
+ end
46
+ }
47
+
48
+ rex.parse
49
+
50
+ output = StringIO.new
51
+ rex.write_scanner output
52
+ assert_match 'Calculator < Bar', output.string
53
+ end
54
+
55
+ def test_scanner_inherits_many_levels
56
+ rex = Rex::Generator.new(
57
+ "--independent" => true
58
+ )
59
+ rex.grammar_lines = StringScanner.new %q{
60
+ class Calculator < Foo::Bar
61
+ rule
62
+ \d+ { [:NUMBER, text.to_i] }
63
+ \s+ { [:S, text] }
64
+ end
65
+ }
66
+
67
+ rex.parse
68
+
69
+ output = StringIO.new
70
+ rex.write_scanner output
71
+ assert_match 'Calculator < Foo::Bar', output.string
72
+ end
73
+
74
+ def test_simple_scanner
75
+ rex = Rex::Generator.new(
76
+ "--independent" => true
77
+ )
78
+ rex.grammar_lines = StringScanner.new %q{
79
+ class Calculator
80
+ rule
81
+ \d+ { [:NUMBER, text.to_i] }
82
+ \s+ { [:S, text] }
83
+ end
84
+ }
85
+
86
+ rex.parse
87
+
88
+ output = StringIO.new
89
+ rex.write_scanner output
90
+
91
+ m = Module.new
92
+ m.module_eval output.string
93
+ calc = m::Calculator.new
94
+ calc.scan_evaluate('1 2 10')
95
+
96
+ assert_tokens [[:NUMBER, 1],
97
+ [:S, ' '],
98
+ [:NUMBER, 2],
99
+ [:S, ' '],
100
+ [:NUMBER, 10]], calc
101
+ end
102
+
103
+ def test_simple_scanner_with_macros
104
+ rex = Rex::Generator.new(
105
+ "--independent" => true
106
+ )
107
+ rex.grammar_lines = StringScanner.new %q{
108
+ class Calculator
109
+ macro
110
+ digit \d+
111
+ rule
112
+ {digit} { [:NUMBER, text.to_i] }
113
+ \s+ { [:S, text] }
114
+ end
115
+ }
116
+
117
+ rex.parse
118
+
119
+ output = StringIO.new
120
+ rex.write_scanner output
121
+
122
+ m = Module.new
123
+ m.module_eval output.string
124
+ calc = m::Calculator.new
125
+ calc.scan_evaluate('1 2 10')
126
+
127
+ assert_tokens [[:NUMBER, 1],
128
+ [:S, ' '],
129
+ [:NUMBER, 2],
130
+ [:S, ' '],
131
+ [:NUMBER, 10]], calc
132
+ end
133
+
134
+ def test_nested_macros
135
+ rex = Rex::Generator.new(
136
+ "--independent" => true
137
+ )
138
+ rex.grammar_lines = StringScanner.new %q{
139
+ class Calculator
140
+ macro
141
+ nonascii [^\0-\177]
142
+ string "{nonascii}*"
143
+ rule
144
+ {string} { [:STRING, text] }
145
+ end
146
+ }
147
+
148
+ rex.parse
149
+
150
+ output = StringIO.new
151
+ rex.write_scanner output
152
+ assert_match '"[^\0-\177]*"', output.string
153
+ end
154
+
155
+ def test_more_nested_macros
156
+ rex = Rex::Generator.new(
157
+ "--independent" => true
158
+ )
159
+ rex.grammar_lines = StringScanner.new %q{
160
+ class Calculator
161
+ macro
162
+ nonascii [^\0-\177]
163
+ sing {nonascii}*
164
+ string "{sing}"
165
+ rule
166
+ {string} { [:STRING, text] }
167
+ end
168
+ }
169
+
170
+ rex.parse
171
+
172
+ output = StringIO.new
173
+ rex.write_scanner output
174
+ assert_match '"[^\0-\177]*"', output.string
175
+ end
176
+
177
+ def assert_tokens expected, scanner
178
+ tokens = []
179
+ while token = scanner.next_token
180
+ tokens << token
181
+ end
182
+ assert_equal expected, tokens
183
+ end
184
+ end