regexp_parser 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +37 -0
- data/README.md +443 -0
- data/Rakefile +28 -46
- data/VERSION.yml +1 -1
- data/lib/regexp_parser/parser.rb +3 -1
- data/lib/regexp_parser/scanner.rb +29 -34
- data/lib/regexp_parser/scanner/scanner.rl +2 -2
- data/lib/regexp_parser/syntax.rb +13 -3
- data/lib/regexp_parser/syntax/ruby/2.0.0.rb +2 -2
- data/lib/regexp_parser/syntax/ruby/2.0.rb +8 -0
- data/lib/regexp_parser/syntax/ruby/2.1.0.rb +2 -2
- data/lib/regexp_parser/syntax/ruby/2.1.2.rb +13 -0
- data/lib/regexp_parser/syntax/ruby/2.1.3.rb +13 -0
- data/lib/regexp_parser/syntax/ruby/2.1.rb +8 -0
- data/test/parser/test_alternation.rb +11 -0
- data/test/parser/test_sets.rb +7 -0
- data/test/scanner/test_sets.rb +1 -0
- data/test/syntax/ruby/test_2.x.rb +46 -0
- data/test/syntax/ruby/test_all.rb +1 -1
- metadata +15 -14
- data/README.rdoc +0 -307
- data/test/scanner/test_conditionals.rb +0 -31
- data/test/scanner/test_quoting.rb +0 -29
data/Rakefile
CHANGED
@@ -1,32 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
1
3
|
require 'rake'
|
2
4
|
require 'rake/testtask'
|
5
|
+
|
6
|
+
require 'bundler'
|
3
7
|
require 'rubygems/package_task'
|
4
|
-
require 'yaml'
|
5
8
|
|
6
|
-
task :default => [:test]
|
7
9
|
|
8
10
|
RAGEL_SOURCE_DIR = File.expand_path '../lib/regexp_parser/scanner', __FILE__
|
9
11
|
RAGEL_OUTPUT_DIR = File.expand_path '../lib/regexp_parser', __FILE__
|
12
|
+
RAGEL_SOURCE_FILES = %w{scanner} # scanner.rl includes property.rl
|
13
|
+
|
10
14
|
|
11
|
-
|
15
|
+
Bundler::GemHelper.install_tasks
|
16
|
+
|
17
|
+
|
18
|
+
task :default => [:test]
|
19
|
+
|
20
|
+
Rake::TestTask.new('test') do |t|
|
21
|
+
t.description = "Run all unit tests under the test directory"
|
12
22
|
|
13
|
-
desc "Find and run all unit tests under test/ directory"
|
14
|
-
Rake::TestTask.new("test") do |t|
|
15
23
|
t.libs << "test"
|
16
|
-
t.test_files = FileList['test
|
24
|
+
t.test_files = FileList['test/test_all.rb']
|
17
25
|
end
|
18
26
|
|
19
|
-
task :test
|
20
|
-
|
21
27
|
namespace :test do
|
22
28
|
%w{scanner lexer parser expression syntax}.each do |component|
|
23
29
|
Rake::TestTask.new(component) do |t|
|
30
|
+
t.description = "Run all #{component} unit tests under the test/#{component} directory"
|
31
|
+
|
24
32
|
t.libs << "test"
|
25
33
|
t.test_files = ["test/#{component}/test_all.rb"]
|
26
34
|
end
|
27
35
|
end
|
36
|
+
|
37
|
+
Rake::TestTask.new('full' => 'ragel:rb') do |t|
|
38
|
+
t.description = "Regenerate the scanner and run all unit tests under the test directory"
|
39
|
+
|
40
|
+
t.libs << "test"
|
41
|
+
t.test_files = FileList['test/test_all.rb']
|
42
|
+
end
|
28
43
|
end
|
29
44
|
|
45
|
+
|
30
46
|
namespace :ragel do
|
31
47
|
desc "Process the ragel source files and output ruby code"
|
32
48
|
task :rb do |t|
|
@@ -44,43 +60,9 @@ namespace :ragel do
|
|
44
60
|
end
|
45
61
|
end
|
46
62
|
|
47
|
-
spec = Gem::Specification.new do |gem|
|
48
|
-
gem.name = 'regexp_parser'
|
49
|
-
gem.version = YAML.load(File.read('VERSION.yml')).values.compact.join('.')
|
50
|
-
gem.date = '2014-01-14'
|
51
|
-
|
52
|
-
gem.license = 'MIT'
|
53
|
-
gem.summary = %q{Scanner, lexer, parser for ruby's regular expressions}
|
54
|
-
gem.description = %q{A library for tokenizing, lexing, and parsing Ruby regular expressions.}
|
55
|
-
gem.homepage = %q{http://github.com/ammar/regexp_parser}
|
56
|
-
|
57
|
-
gem.authors = ["Ammar Ali"]
|
58
|
-
gem.email = 'ammarabuali@gmail.com'
|
59
|
-
|
60
|
-
gem.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
61
|
-
gem.extra_rdoc_files = ["ChangeLog", "LICENSE", "README.rdoc"]
|
62
|
-
|
63
|
-
gem.require_paths = ["lib"]
|
64
|
-
|
65
|
-
gem.files = Dir.glob("{lib,test}/**/*.rb") + Dir.glob("lib/**/*.rl") +
|
66
|
-
%w(VERSION.yml Rakefile LICENSE README.rdoc ChangeLog)
|
67
63
|
|
68
|
-
|
64
|
+
# Add ragel task as a prerequisite for building the gem to ensure that the
|
65
|
+
# latest scanner code is generated and included in the build.
|
66
|
+
desc "Runs ragel:rb before building the gem"
|
67
|
+
task :build => ['ragel:rb']
|
69
68
|
|
70
|
-
gem.required_rubygems_version = Gem::Requirement.new(">= 0") if
|
71
|
-
gem.respond_to? :required_rubygems_version=
|
72
|
-
end
|
73
|
-
|
74
|
-
Gem::PackageTask.new(spec) do |pkg|
|
75
|
-
pkg.need_zip = true
|
76
|
-
pkg.need_tar = true
|
77
|
-
end
|
78
|
-
|
79
|
-
namespace :gem do
|
80
|
-
desc "Release the gem to rubygems.org"
|
81
|
-
task :release do |t|
|
82
|
-
Rake::Task['ragel:rb'].execute
|
83
|
-
Rake::Task['repackage'].execute
|
84
|
-
#sh "gem push"
|
85
|
-
end
|
86
|
-
end
|
data/VERSION.yml
CHANGED
data/lib/regexp_parser/parser.rb
CHANGED
@@ -406,8 +406,10 @@ module Regexp::Parser
|
|
406
406
|
end
|
407
407
|
|
408
408
|
def self.close_group
|
409
|
-
|
409
|
+
@nesting.pop
|
410
|
+
|
410
411
|
@node = @nesting.last
|
412
|
+
@node = @node.last if @node.last and @node.last.is_a?(Alternation)
|
411
413
|
end
|
412
414
|
|
413
415
|
def self.open_set(token)
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
|
7
7
|
# THIS IS A GENERATED FILE, DO NOT EDIT DIRECTLY
|
8
|
-
# This file was generated from scanner.rl
|
8
|
+
# This file was generated from lib/regexp_parser/scanner/scanner.rl
|
9
9
|
|
10
10
|
module Regexp::Scanner
|
11
11
|
|
@@ -1226,7 +1226,7 @@ self._re_scanner_trans_targs = [
|
|
1226
1226
|
154, 155, 156, 145, 145, 145, 145, 45,
|
1227
1227
|
47, 50, 145, 145, 51, 145, 145, 52,
|
1228
1228
|
55, 103, 106, 107, 109, 161, 162, 157,
|
1229
|
-
162,
|
1229
|
+
162, 157, 157, 157, 163, 157, 164, 157,
|
1230
1230
|
112, 166, 157, 157, 167, 167, 168, 168,
|
1231
1231
|
167, 115, 116, 167, 167, 119, 129, 167,
|
1232
1232
|
169, 167, 167, 167, 167, 117, 167, 167,
|
@@ -2292,6 +2292,30 @@ te = p+1
|
|
2292
2292
|
next
|
2293
2293
|
end
|
2294
2294
|
|
2295
|
+
end
|
2296
|
+
end
|
2297
|
+
when 69 then
|
2298
|
+
# line 242 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
2299
|
+
begin
|
2300
|
+
te = p+1
|
2301
|
+
begin
|
2302
|
+
case text = text(data, ts, te, 1).first
|
2303
|
+
when '\d'; emit(set_type, :type_digit, text, ts-1, te)
|
2304
|
+
when '\D'; emit(set_type, :type_nondigit, text, ts-1, te)
|
2305
|
+
when '\h'; emit(set_type, :type_hex, text, ts-1, te)
|
2306
|
+
when '\H'; emit(set_type, :type_nonhex, text, ts-1, te)
|
2307
|
+
when '\s'; emit(set_type, :type_space, text, ts-1, te)
|
2308
|
+
when '\S'; emit(set_type, :type_nonspace, text, ts-1, te)
|
2309
|
+
when '\w'; emit(set_type, :type_word, text, ts-1, te)
|
2310
|
+
when '\W'; emit(set_type, :type_nonword, text, ts-1, te)
|
2311
|
+
end
|
2312
|
+
begin
|
2313
|
+
top -= 1
|
2314
|
+
cs = stack[top]
|
2315
|
+
_goto_level = _again
|
2316
|
+
next
|
2317
|
+
end
|
2318
|
+
|
2295
2319
|
end
|
2296
2320
|
end
|
2297
2321
|
when 75 then
|
@@ -2419,27 +2443,6 @@ p = p - 1; begin
|
|
2419
2443
|
next
|
2420
2444
|
end
|
2421
2445
|
end
|
2422
|
-
when 15 then
|
2423
|
-
begin begin p = ((te))-1; end
|
2424
|
-
|
2425
|
-
case text = text(data, ts, te, 1).first
|
2426
|
-
when '\d'; emit(set_type, :type_digit, text, ts-1, te)
|
2427
|
-
when '\D'; emit(set_type, :type_nondigit, text, ts-1, te)
|
2428
|
-
when '\h'; emit(set_type, :type_hex, text, ts-1, te)
|
2429
|
-
when '\H'; emit(set_type, :type_nonhex, text, ts-1, te)
|
2430
|
-
when '\s'; emit(set_type, :type_space, text, ts-1, te)
|
2431
|
-
when '\S'; emit(set_type, :type_nonspace, text, ts-1, te)
|
2432
|
-
when '\w'; emit(set_type, :type_word, text, ts-1, te)
|
2433
|
-
when '\W'; emit(set_type, :type_nonword, text, ts-1, te)
|
2434
|
-
end
|
2435
|
-
begin
|
2436
|
-
top -= 1
|
2437
|
-
cs = stack[top]
|
2438
|
-
_goto_level = _again
|
2439
|
-
next
|
2440
|
-
end
|
2441
|
-
|
2442
|
-
end
|
2443
2446
|
when 18 then
|
2444
2447
|
begin begin p = ((te))-1; end
|
2445
2448
|
|
@@ -3428,14 +3431,6 @@ te = p+1
|
|
3428
3431
|
# line 136 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3429
3432
|
begin
|
3430
3433
|
group_depth += 1; in_group = true end
|
3431
|
-
when 69 then
|
3432
|
-
# line 1 "NONE"
|
3433
|
-
begin
|
3434
|
-
te = p+1
|
3435
|
-
end
|
3436
|
-
# line 242 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3437
|
-
begin
|
3438
|
-
act = 15; end
|
3439
3434
|
when 68 then
|
3440
3435
|
# line 1 "NONE"
|
3441
3436
|
begin
|
@@ -3476,7 +3471,7 @@ te = p+1
|
|
3476
3471
|
# line 672 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3477
3472
|
begin
|
3478
3473
|
act = 53; end
|
3479
|
-
# line
|
3474
|
+
# line 3475 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner.rb"
|
3480
3475
|
end
|
3481
3476
|
end
|
3482
3477
|
end
|
@@ -3494,7 +3489,7 @@ ts = nil; end
|
|
3494
3489
|
begin
|
3495
3490
|
act = 0
|
3496
3491
|
end
|
3497
|
-
# line
|
3492
|
+
# line 3493 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner.rb"
|
3498
3493
|
end
|
3499
3494
|
|
3500
3495
|
if cs == 0
|
@@ -3528,7 +3523,7 @@ act = 0
|
|
3528
3523
|
text = ts ? copy(data, ts-1..-1) : data.pack('c*')
|
3529
3524
|
raise PrematureEndError.new( text )
|
3530
3525
|
end
|
3531
|
-
# line
|
3526
|
+
# line 3527 "/Users/ammar/src/ruby/projects/regexp_parser/lib/regexp_parser/scanner.rb"
|
3532
3527
|
end
|
3533
3528
|
end
|
3534
3529
|
|
@@ -239,7 +239,7 @@
|
|
239
239
|
fret;
|
240
240
|
};
|
241
241
|
|
242
|
-
char_type {
|
242
|
+
char_type > (escaped_set_alpha, 4) {
|
243
243
|
case text = text(data, ts, te, 1).first
|
244
244
|
when '\d'; emit(set_type, :type_digit, text, ts-1, te)
|
245
245
|
when '\D'; emit(set_type, :type_nondigit, text, ts-1, te)
|
@@ -677,7 +677,7 @@
|
|
677
677
|
}%%
|
678
678
|
|
679
679
|
# THIS IS A GENERATED FILE, DO NOT EDIT DIRECTLY
|
680
|
-
# This file was generated from scanner.rl
|
680
|
+
# This file was generated from lib/regexp_parser/scanner/scanner.rl
|
681
681
|
|
682
682
|
module Regexp::Scanner
|
683
683
|
%% write data;
|
data/lib/regexp_parser/syntax.rb
CHANGED
@@ -37,12 +37,15 @@ module Regexp::Syntax
|
|
37
37
|
self.load(name)
|
38
38
|
|
39
39
|
case name
|
40
|
+
# Ruby 1.8.x (NOTE: 1.8.6 is no longer a supported runtime,
|
41
|
+
# but its regex features are still recognized.)
|
40
42
|
when 'ruby/1.8.6'; syntax = Regexp::Syntax::Ruby::V186.new
|
41
43
|
when 'ruby/1.8.7'; syntax = Regexp::Syntax::Ruby::V187.new
|
42
44
|
|
43
45
|
# alias for the latest 1.8 implementation
|
44
46
|
when 'ruby/1.8'; syntax = Regexp::Syntax::Ruby::V18.new
|
45
47
|
|
48
|
+
# Ruby 1.9.x
|
46
49
|
when 'ruby/1.9.1'; syntax = Regexp::Syntax::Ruby::V191.new
|
47
50
|
when 'ruby/1.9.2'; syntax = Regexp::Syntax::Ruby::V192.new
|
48
51
|
when 'ruby/1.9.3'; syntax = Regexp::Syntax::Ruby::V193.new
|
@@ -50,11 +53,18 @@ module Regexp::Syntax
|
|
50
53
|
# alias for the latest 1.9 implementation
|
51
54
|
when 'ruby/1.9'; syntax = Regexp::Syntax::Ruby::V19.new
|
52
55
|
|
53
|
-
|
54
|
-
when 'ruby/2.
|
56
|
+
# Ruby 2.0.x
|
57
|
+
when 'ruby/2.0.0'; syntax = Regexp::Syntax::Ruby::V200.new
|
55
58
|
|
56
|
-
# aliases for the latest 2.
|
59
|
+
# aliases for the latest 2.0 implementations
|
57
60
|
when 'ruby/2.0'; syntax = Regexp::Syntax::Ruby::V20.new
|
61
|
+
|
62
|
+
# Ruby 2.1.x
|
63
|
+
when 'ruby/2.1.0'; syntax = Regexp::Syntax::Ruby::V210.new
|
64
|
+
when 'ruby/2.1.2'; syntax = Regexp::Syntax::Ruby::V212.new
|
65
|
+
when 'ruby/2.1.3'; syntax = Regexp::Syntax::Ruby::V213.new
|
66
|
+
|
67
|
+
# aliases for the latest 2.1 implementations
|
58
68
|
when 'ruby/2.1'; syntax = Regexp::Syntax::Ruby::V21.new
|
59
69
|
|
60
70
|
else
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require File.expand_path('../1.9
|
1
|
+
require File.expand_path('../1.9', __FILE__)
|
2
2
|
|
3
3
|
module Regexp::Syntax
|
4
4
|
module Ruby
|
5
5
|
|
6
6
|
# use the last 1.9 release as the base
|
7
|
-
class
|
7
|
+
class V200 < Regexp::Syntax::Ruby::V19
|
8
8
|
def initialize
|
9
9
|
super
|
10
10
|
|
@@ -78,4 +78,15 @@ class ParserAlternation < Test::Unit::TestCase
|
|
78
78
|
assert_equal( true, subalts[1].is_a?(Sequence) )
|
79
79
|
end
|
80
80
|
|
81
|
+
def test_parse_alternation_continues_after_nesting
|
82
|
+
root = RP.parse(/a|(b)c/)
|
83
|
+
|
84
|
+
seq = root.expressions[0][1].expressions
|
85
|
+
|
86
|
+
assert_equal( 2, seq.length )
|
87
|
+
|
88
|
+
assert_equal( true, seq[0].is_a?(Group::Capture) )
|
89
|
+
assert_equal( true, seq[1].is_a?(Literal) )
|
90
|
+
end
|
91
|
+
|
81
92
|
end
|
data/test/parser/test_sets.rb
CHANGED
@@ -36,6 +36,13 @@ class TestParserSets < Test::Unit::TestCase
|
|
36
36
|
assert_equal( false, exp.include?(']') )
|
37
37
|
end
|
38
38
|
|
39
|
+
def test_parse_chat_type_set_members
|
40
|
+
exp = RP.parse('[\da-z]', :any)[0]
|
41
|
+
|
42
|
+
assert_equal( true, exp.include?('\d') )
|
43
|
+
assert_equal( true, exp.include?('a-z') )
|
44
|
+
end
|
45
|
+
|
39
46
|
def test_parse_set_collating_sequence
|
40
47
|
exp = RP.parse('[a[.span-ll.]h]', :any)[0]
|
41
48
|
|
data/test/scanner/test_sets.rb
CHANGED
@@ -28,6 +28,7 @@ class ScannerSets < Test::Unit::TestCase
|
|
28
28
|
'[a\-c]' => [2, :set, :escape, '\-', 2, 4],
|
29
29
|
|
30
30
|
'[\d]' => [1, :set, :type_digit, '\d', 1, 3],
|
31
|
+
'[\da-z]' => [1, :set, :type_digit, '\d', 1, 3],
|
31
32
|
'[\D]' => [1, :set, :type_nondigit, '\D', 1, 3],
|
32
33
|
|
33
34
|
'[\h]' => [1, :set, :type_hex, '\h', 1, 3],
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path("../../../helpers", __FILE__)
|
2
|
+
|
3
|
+
class TestSyntaxRuby_V2x < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# Since the only Regular expression change that was introduced in ruby 2.x
|
6
|
+
# (the conditional expressions) is not supportted yet, these tests only
|
7
|
+
# check that the syntax files have the correct inheritance (based off the
|
8
|
+
# last release) and load without error.
|
9
|
+
|
10
|
+
def test_syntax_file_2_0_0
|
11
|
+
syntax = Regexp::Syntax.new 'ruby/2.0.0'
|
12
|
+
|
13
|
+
assert_equal( true, syntax.kind_of?(Regexp::Syntax::Ruby::V19) )
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_syntax_file_2_0_alias
|
17
|
+
syntax = Regexp::Syntax.new 'ruby/2.0'
|
18
|
+
|
19
|
+
assert_equal( true, syntax.kind_of?(Regexp::Syntax::Ruby::V200) )
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_syntax_file_2_1_0
|
23
|
+
syntax = Regexp::Syntax.new 'ruby/2.1.0'
|
24
|
+
|
25
|
+
assert_equal( true, syntax.kind_of?(Regexp::Syntax::Ruby::V20) )
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_syntax_file_2_1_2
|
29
|
+
syntax = Regexp::Syntax.new 'ruby/2.1.2'
|
30
|
+
|
31
|
+
assert_equal( true, syntax.kind_of?(Regexp::Syntax::Ruby::V210) )
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_syntax_file_2_1_3
|
35
|
+
syntax = Regexp::Syntax.new 'ruby/2.1.3'
|
36
|
+
|
37
|
+
assert_equal( true, syntax.kind_of?(Regexp::Syntax::Ruby::V212) )
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_syntax_file_2_1_alias
|
41
|
+
syntax = Regexp::Syntax.new 'ruby/2.1'
|
42
|
+
|
43
|
+
assert_equal( true, syntax.kind_of?(Regexp::Syntax::Ruby::V213) )
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|