rexical 1.0.5 → 1.0.8
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 +7 -0
- data/CHANGELOG.rdoc +19 -2
- data/COPYING +129 -0
- data/DOCUMENTATION.en.rdoc +210 -214
- data/DOCUMENTATION.ja.rdoc +2 -2
- data/Manifest.txt +2 -0
- data/README.rdoc +15 -7
- data/Rakefile +2 -28
- data/bin/rex +0 -0
- data/lib/rexical/generator.rb +147 -161
- data/lib/rexical/rexcmd.rb +4 -2
- data/lib/rexical/version.rb +5 -0
- data/lib/rexical.rb +3 -8
- data/sample/calc3.tab.rb +1 -1
- data/sample/error1.rex +1 -1
- data/sample/error2.rex +2 -2
- data/sample/sample.rex +1 -1
- data/sample/sample.rex.rb +92 -100
- data/sample/sample1.rex +4 -4
- data/sample/sample2.rex +2 -2
- data/sample/xhtmlparser.rex +15 -15
- data/test/assets/test.rex +4 -0
- data/test/rex-20060125.rb +1 -1
- data/test/rex-20060511.rb +1 -1
- data/test/test_generator.rb +59 -3
- metadata +49 -68
data/sample/sample.rex.rb
CHANGED
@@ -1,100 +1,92 @@
|
|
1
|
-
|
2
|
-
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by rex 1.0.
|
4
|
-
# from lexical definition file "sample.rex".
|
5
|
-
|
6
|
-
|
7
|
-
require 'racc/parser'
|
8
|
-
#
|
9
|
-
# sample.rex
|
10
|
-
# lexical definition sample for rex
|
11
|
-
#
|
12
|
-
|
13
|
-
class Sample < Racc::Parser
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
rex.load_file filename
|
94
|
-
while token = rex.next_token
|
95
|
-
p token
|
96
|
-
end
|
97
|
-
rescue
|
98
|
-
$stderr.printf "%s:%d:%s\n", rex.filename, rex.lineno, $!.message
|
99
|
-
end
|
100
|
-
end
|
1
|
+
#--
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by rex 1.0.5
|
4
|
+
# from lexical definition file "sample/sample.rex".
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'racc/parser'
|
8
|
+
#
|
9
|
+
# sample.rex
|
10
|
+
# lexical definition sample for rex
|
11
|
+
#
|
12
|
+
|
13
|
+
class Sample < Racc::Parser
|
14
|
+
require 'strscan'
|
15
|
+
|
16
|
+
class ScanError < StandardError ; end
|
17
|
+
|
18
|
+
attr_reader :lineno
|
19
|
+
attr_reader :filename
|
20
|
+
attr_accessor :state
|
21
|
+
|
22
|
+
def scan_setup(str)
|
23
|
+
@ss = StringScanner.new(str)
|
24
|
+
@lineno = 1
|
25
|
+
@state = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def action
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
|
32
|
+
def scan_str(str)
|
33
|
+
scan_setup(str)
|
34
|
+
do_parse
|
35
|
+
end
|
36
|
+
alias :scan :scan_str
|
37
|
+
|
38
|
+
def load_file( filename )
|
39
|
+
@filename = filename
|
40
|
+
open(filename, "r") do |f|
|
41
|
+
scan_setup(f.read)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def scan_file( filename )
|
46
|
+
load_file(filename)
|
47
|
+
do_parse
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def next_token
|
52
|
+
return if @ss.eos?
|
53
|
+
|
54
|
+
# skips empty actions
|
55
|
+
until token = _next_token or @ss.eos?; end
|
56
|
+
token
|
57
|
+
end
|
58
|
+
|
59
|
+
def _next_token
|
60
|
+
text = @ss.peek(1)
|
61
|
+
@lineno += 1 if text == "\n"
|
62
|
+
token = case @state
|
63
|
+
when nil
|
64
|
+
case
|
65
|
+
when (text = @ss.scan(/[ \t]+/))
|
66
|
+
;
|
67
|
+
|
68
|
+
when (text = @ss.scan(/\d+/))
|
69
|
+
action { [:digit, text.to_i] }
|
70
|
+
|
71
|
+
when (text = @ss.scan(/\w+/))
|
72
|
+
action { [:word, text] }
|
73
|
+
|
74
|
+
when (text = @ss.scan(/\n/))
|
75
|
+
;
|
76
|
+
|
77
|
+
when (text = @ss.scan(/./))
|
78
|
+
action { [text, text] }
|
79
|
+
|
80
|
+
|
81
|
+
else
|
82
|
+
text = @ss.string[@ss.pos .. -1]
|
83
|
+
raise ScanError, "can not match: '" + text + "'"
|
84
|
+
end # if
|
85
|
+
|
86
|
+
else
|
87
|
+
raise ScanError, "undefined state: '" + state.to_s + "'"
|
88
|
+
end # case state
|
89
|
+
token
|
90
|
+
end # def _next_token
|
91
|
+
|
92
|
+
end # class
|
data/sample/sample1.rex
CHANGED
@@ -19,11 +19,11 @@ rule
|
|
19
19
|
# [:state] pattern [actions]
|
20
20
|
|
21
21
|
# remark
|
22
|
-
{REM_IN} { state = :REMS; [:rem_in, text] }
|
23
|
-
:REMS {REM_OUT} { state = nil; [:rem_out, text] }
|
22
|
+
{REM_IN} { self.state = :REMS; [:rem_in, text] }
|
23
|
+
:REMS {REM_OUT} { self.state = nil; [:rem_out, text] }
|
24
24
|
:REMS .*(?={REM_OUT}) { [:remark, text] }
|
25
|
-
{REM} { state = :REM; [:rem_in, text] }
|
26
|
-
:REM \n { state = nil; [:rem_out, text] }
|
25
|
+
{REM} { self.state = :REM; [:rem_in, text] }
|
26
|
+
:REM \n { self.state = nil; [:rem_out, text] }
|
27
27
|
:REM .*(?=$) { [:remark, text] }
|
28
28
|
|
29
29
|
# literal
|
data/sample/sample2.rex
CHANGED
@@ -16,8 +16,8 @@ macro
|
|
16
16
|
REMARK \' # '
|
17
17
|
|
18
18
|
rule
|
19
|
-
{REMARK} { state = :REM; [:rem_in, text] } # '
|
20
|
-
:REM \n { state = nil; [:rem_out, text] }
|
19
|
+
{REMARK} { self.state = :REM; [:rem_in, text] } # '
|
20
|
+
:REM \n { self.state = nil; [:rem_out, text] }
|
21
21
|
:REM .*(?=$) { [:remark, text] }
|
22
22
|
|
23
23
|
\"[^"]*\" { [:string, text] } # "
|
data/sample/xhtmlparser.rex
CHANGED
@@ -28,34 +28,34 @@ macro
|
|
28
28
|
rule
|
29
29
|
|
30
30
|
# [:state] pattern [actions]
|
31
|
-
{XTAG_IN} { state = :TAG; [:xtag_in, text] }
|
32
|
-
{ETAG_IN} { state = :TAG; [:etag_in, text] }
|
33
|
-
{TAG_IN} { state = :TAG; [:tag_in, text] }
|
34
|
-
:TAG {EXT} { state = :EXT; [:ext, text] }
|
31
|
+
{XTAG_IN} { self.state = :TAG; [:xtag_in, text] }
|
32
|
+
{ETAG_IN} { self.state = :TAG; [:etag_in, text] }
|
33
|
+
{TAG_IN} { self.state = :TAG; [:tag_in, text] }
|
34
|
+
:TAG {EXT} { self.state = :EXT; [:ext, text] }
|
35
35
|
|
36
|
-
:EXT {REM} { state = :REM; [:rem_in, text] }
|
37
|
-
:EXT {XTAG_OUT} { state = nil; [:xtag_out, text] }
|
38
|
-
:EXT {TAG_OUT} { state = nil; [:tag_out, text] }
|
36
|
+
:EXT {REM} { self.state = :REM; [:rem_in, text] }
|
37
|
+
:EXT {XTAG_OUT} { self.state = nil; [:xtag_out, text] }
|
38
|
+
:EXT {TAG_OUT} { self.state = nil; [:tag_out, text] }
|
39
39
|
:EXT .+(?={REM}) { [:exttext, text] }
|
40
40
|
:EXT .+(?={TAG_OUT}) { [:exttext, text] }
|
41
41
|
:EXT .+(?=$) { [:exttext, text] }
|
42
42
|
:EXT \n
|
43
43
|
|
44
|
-
:REM {REM} { state = :EXT; [:rem_out, text] }
|
44
|
+
:REM {REM} { self.state = :EXT; [:rem_out, text] }
|
45
45
|
:REM .+(?={REM}) { [:remtext, text] }
|
46
46
|
:REM .+(?=$) { [:remtext, text] }
|
47
47
|
:REM \n
|
48
48
|
|
49
49
|
:TAG {BLANK}
|
50
|
-
:TAG {XTAG_OUT} { state = nil; [:xtag_out, text] }
|
51
|
-
:TAG {ETAG_OUT} { state = nil; [:etag_out, text] }
|
52
|
-
:TAG {TAG_OUT} { state = nil; [:tag_out, text] }
|
50
|
+
:TAG {XTAG_OUT} { self.state = nil; [:xtag_out, text] }
|
51
|
+
:TAG {ETAG_OUT} { self.state = nil; [:etag_out, text] }
|
52
|
+
:TAG {TAG_OUT} { self.state = nil; [:tag_out, text] }
|
53
53
|
:TAG {EQUAL} { [:equal, text] }
|
54
|
-
:TAG {Q1} { state = :Q1; [:quote1, text] } # '
|
55
|
-
:Q1 {Q1} { state = :TAG; [:quote1, text] } # '
|
54
|
+
:TAG {Q1} { self.state = :Q1; [:quote1, text] } # '
|
55
|
+
:Q1 {Q1} { self.state = :TAG; [:quote1, text] } # '
|
56
56
|
:Q1 [^{Q1}]+(?={Q1}) { [:value, text] } # '
|
57
|
-
:TAG {Q2} { state = :Q2; [:quote2, text] } # "
|
58
|
-
:Q2 {Q2} { state = :TAG; [:quote2, text] } # "
|
57
|
+
:TAG {Q2} { self.state = :Q2; [:quote2, text] } # "
|
58
|
+
:Q2 {Q2} { self.state = :TAG; [:quote2, text] } # "
|
59
59
|
:Q2 [^{Q2}]+(?={Q2}) { [:value, text] } # "
|
60
60
|
|
61
61
|
:TAG [\w\-]+(?={EQUAL}) { [:attr, text] }
|
data/test/assets/test.rex
CHANGED
data/test/rex-20060125.rb
CHANGED
@@ -91,7 +91,7 @@ def get_options
|
|
91
91
|
"#{$cmd}: #{name} given twice" if opt.key? name
|
92
92
|
opt[name] = arg.empty? ? true : arg
|
93
93
|
end
|
94
|
-
rescue GetoptLong::
|
94
|
+
rescue GetoptLong::AmbiguousOption, GetoptLong::InvalidOption,
|
95
95
|
GetoptLong::MissingArgument, GetoptLong::NeedlessArgument
|
96
96
|
usage 1, $!.message
|
97
97
|
end
|
data/test/rex-20060511.rb
CHANGED
@@ -89,7 +89,7 @@ class RexRunner
|
|
89
89
|
"#{@cmd}: #{name} given twice" if @opt.key? name
|
90
90
|
@opt[name] = arg.empty? ? true : arg
|
91
91
|
end
|
92
|
-
rescue GetoptLong::
|
92
|
+
rescue GetoptLong::AmbiguousOption, GetoptLong::InvalidOption,
|
93
93
|
GetoptLong::MissingArgument, GetoptLong::NeedlessArgument
|
94
94
|
usage $!.message
|
95
95
|
end
|
data/test/test_generator.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
gem "minitest"
|
2
|
+
require 'minitest/autorun'
|
2
3
|
require 'tempfile'
|
3
4
|
require 'rexical'
|
4
5
|
require 'stringio'
|
6
|
+
require 'open3'
|
5
7
|
|
6
|
-
class TestGenerator < Test
|
8
|
+
class TestGenerator < Minitest::Test
|
7
9
|
def test_header_is_written_after_module
|
8
10
|
rex = Rexical::Generator.new(
|
9
11
|
"--independent" => true
|
@@ -25,6 +27,29 @@ class TestGenerator < Test::Unit::TestCase
|
|
25
27
|
assert_equal '#++', comments.last
|
26
28
|
end
|
27
29
|
|
30
|
+
def test_rubocop_security
|
31
|
+
rex = Rexical::Generator.new(
|
32
|
+
"--independent" => true
|
33
|
+
)
|
34
|
+
rex.grammar_file = File.join File.dirname(__FILE__), 'assets', 'test.rex'
|
35
|
+
rex.read_grammar
|
36
|
+
rex.parse
|
37
|
+
|
38
|
+
output = Tempfile.new(["rex_output", ".rb"])
|
39
|
+
begin
|
40
|
+
rex.write_scanner output
|
41
|
+
output.close
|
42
|
+
|
43
|
+
stdin, stdoe, wait_thr = Open3.popen2e "rubocop --only Security #{output.path}"
|
44
|
+
if ! wait_thr.value.success?
|
45
|
+
fail stdoe.read
|
46
|
+
end
|
47
|
+
ensure
|
48
|
+
output.close
|
49
|
+
output.unlink
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
28
53
|
def test_read_non_existent_file
|
29
54
|
rex = Rexical::Generator.new(nil)
|
30
55
|
rex.grammar_file = 'non_existent_file'
|
@@ -71,6 +96,22 @@ end
|
|
71
96
|
assert_match 'Calculator < Foo::Bar', source
|
72
97
|
end
|
73
98
|
|
99
|
+
def test_stateful_lexer
|
100
|
+
m = build_lexer %q{
|
101
|
+
class Foo
|
102
|
+
rule
|
103
|
+
\d { @state = :digit; [:foo, text] }
|
104
|
+
:digit \w { @state = nil; [:w, text] }
|
105
|
+
end
|
106
|
+
}
|
107
|
+
scanner = m::Foo.new
|
108
|
+
scanner.scan_setup('1w1')
|
109
|
+
assert_tokens [
|
110
|
+
[:foo, '1'],
|
111
|
+
[:w, 'w'],
|
112
|
+
[:foo, '1']], scanner
|
113
|
+
end
|
114
|
+
|
74
115
|
def test_simple_scanner
|
75
116
|
m = build_lexer %q{
|
76
117
|
class Calculator
|
@@ -185,7 +226,7 @@ end
|
|
185
226
|
calc2.scan_setup('ababa')
|
186
227
|
|
187
228
|
# Doesn't lex all 'a's
|
188
|
-
|
229
|
+
assert_raises(lexer::Calculator::ScanError) { tokens(calc1) }
|
189
230
|
|
190
231
|
# Does lex alternating 'a's and 'b's
|
191
232
|
calc2.scan_setup('ababa')
|
@@ -219,6 +260,21 @@ end
|
|
219
260
|
calc.state = nil
|
220
261
|
assert_equal [:A, 'a'], calc.next_token
|
221
262
|
end
|
263
|
+
def test_match_eos
|
264
|
+
lexer = build_lexer %q{
|
265
|
+
class Calculator
|
266
|
+
option
|
267
|
+
matcheos
|
268
|
+
rule
|
269
|
+
a { [:A, text] }
|
270
|
+
$ { [:EOF, ""] }
|
271
|
+
:B b { [:B, text] }
|
272
|
+
}
|
273
|
+
calc = lexer::Calculator.new
|
274
|
+
calc.scan_setup("a")
|
275
|
+
assert_equal [:A, 'a'], calc.next_token
|
276
|
+
assert_equal [:EOF, ""], calc.next_token
|
277
|
+
end
|
222
278
|
|
223
279
|
def parse_lexer(str)
|
224
280
|
rex = Rexical::Generator.new("--independent" => true)
|
metadata
CHANGED
@@ -1,55 +1,43 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rexical
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 1
|
7
|
-
- 0
|
8
|
-
- 5
|
9
|
-
version: 1.0.5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.8
|
10
5
|
platform: ruby
|
11
|
-
authors:
|
6
|
+
authors:
|
12
7
|
- Aaron Patterson
|
13
|
-
autorequire:
|
8
|
+
autorequire:
|
14
9
|
bindir: bin
|
15
10
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
date: 2024-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: getoptlong
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
22
21
|
prerelease: false
|
23
|
-
|
24
|
-
|
25
|
-
requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
26
24
|
- - ">="
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
type: :development
|
34
|
-
version_requirements: *id001
|
35
|
-
description: |-
|
36
|
-
Rexical is a lexical scanner generator.
|
37
|
-
It is written in Ruby itself, and generates Ruby program.
|
38
|
-
It is designed for use with Racc.
|
39
|
-
email:
|
40
|
-
- aaronp@rubyforge.org
|
41
|
-
executables:
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Rexical is a lexical scanner generator that is used with Racc to generate
|
28
|
+
Ruby programs. Rexical is written in Ruby.
|
29
|
+
email:
|
30
|
+
executables:
|
42
31
|
- rex
|
43
32
|
extensions: []
|
44
|
-
|
45
|
-
extra_rdoc_files:
|
46
|
-
- Manifest.txt
|
33
|
+
extra_rdoc_files:
|
47
34
|
- CHANGELOG.rdoc
|
48
35
|
- DOCUMENTATION.en.rdoc
|
49
36
|
- DOCUMENTATION.ja.rdoc
|
50
37
|
- README.rdoc
|
51
|
-
files:
|
38
|
+
files:
|
52
39
|
- CHANGELOG.rdoc
|
40
|
+
- COPYING
|
53
41
|
- DOCUMENTATION.en.rdoc
|
54
42
|
- DOCUMENTATION.ja.rdoc
|
55
43
|
- Manifest.txt
|
@@ -60,6 +48,7 @@ files:
|
|
60
48
|
- lib/rexical.rb
|
61
49
|
- lib/rexical/generator.rb
|
62
50
|
- lib/rexical/rexcmd.rb
|
51
|
+
- lib/rexical/version.rb
|
63
52
|
- sample/a.cmd
|
64
53
|
- sample/b.cmd
|
65
54
|
- sample/c.cmd
|
@@ -85,38 +74,30 @@ files:
|
|
85
74
|
- test/rex-20060125.rb
|
86
75
|
- test/rex-20060511.rb
|
87
76
|
- test/test_generator.rb
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
post_install_message:
|
93
|
-
rdoc_options:
|
94
|
-
- --main
|
77
|
+
homepage: http://github.com/sparklemotion/rexical
|
78
|
+
licenses:
|
79
|
+
- LGPL-2.1-only
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options:
|
83
|
+
- "--main"
|
95
84
|
- README.rdoc
|
96
|
-
require_paths:
|
85
|
+
require_paths:
|
97
86
|
- lib
|
98
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
-
|
100
|
-
requirements:
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
101
89
|
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
-
none: false
|
108
|
-
requirements:
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
109
94
|
- - ">="
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
|
112
|
-
- 0
|
113
|
-
version: "0"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
114
97
|
requirements: []
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
test_files:
|
122
|
-
- test/test_generator.rb
|
98
|
+
rubygems_version: 3.5.10
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Rexical is a lexical scanner generator that is used with Racc to generate
|
102
|
+
Ruby programs
|
103
|
+
test_files: []
|