parsr 0.0.3 → 0.0.4
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.
- data/.travis.yml +9 -0
- data/README.md +3 -1
- data/Rakefile +7 -0
- data/lib/parsr.rb +4 -23
- data/lib/parsr/rules.rb +15 -0
- data/lib/parsr/rules/all.rb +14 -0
- data/lib/parsr/{array_rule.rb → rules/array.rb} +2 -2
- data/lib/parsr/{constants_rule.rb → rules/constants.rb} +1 -1
- data/lib/parsr/{float_rule.rb → rules/float.rb} +3 -2
- data/lib/parsr/{hash_rule.rb → rules/hash.rb} +1 -1
- data/lib/parsr/{integer_rule.rb → rules/integer.rb} +3 -2
- data/lib/parsr/rules/numeric.rb +6 -0
- data/lib/parsr/{range_rule.rb → rules/range.rb} +2 -2
- data/lib/parsr/{raw_string_rule.rb → rules/raw_string.rb} +1 -1
- data/lib/parsr/rules/regexp.rb +40 -0
- data/lib/parsr/{string_rule.rb → rules/string.rb} +1 -1
- data/lib/parsr/{symbol_rule.rb → rules/symbol.rb} +1 -1
- data/lib/parsr/version.rb +1 -1
- data/parsr.gemspec +1 -0
- data/spec/parsr/{array_rule_spec.rb → rules/array_spec.rb} +1 -1
- data/spec/parsr/{constants_rule_spec.rb → rules/constants_spec.rb} +1 -1
- data/spec/parsr/{float_rule_spec.rb → rules/float_spec.rb} +5 -1
- data/spec/parsr/{hash_rule_spec.rb → rules/hash_spec.rb} +1 -1
- data/spec/parsr/{integer_rule_spec.rb → rules/integer_spec.rb} +12 -1
- data/spec/parsr/{range_rule_spec.rb → rules/range_spec.rb} +1 -1
- data/spec/parsr/{raw_string_rule_spec.rb → rules/raw_string_spec.rb} +2 -2
- data/spec/parsr/rules/regexp_spec.rb +46 -0
- data/spec/parsr/{string_rule_spec.rb → rules/string_spec.rb} +1 -1
- data/spec/parsr/{symbol_rule_spec.rb → rules/symbol_spec.rb} +1 -1
- data/spec/parsr_spec.rb +2 -2
- data/spec/spec_helper.rb +0 -1
- metadata +98 -57
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -6,5 +6,7 @@ just as Python's [ast.literal_eval](http://docs.python.org/library/ast.html#ast.
|
|
6
6
|
## Example
|
7
7
|
|
8
8
|
```ruby
|
9
|
-
Parsr.literal_eval(%q{ [1, "2", 3.4 => 5..6, foo: [7] ] })
|
9
|
+
Parsr.literal_eval(%q{ [1, "2", 3.4 => 5..6, foo: [7, bar: /(bb|[^b]{2})/ix] ] })
|
10
10
|
```
|
11
|
+
|
12
|
+
[](http://travis-ci.org/byroot/parsr)
|
data/Rakefile
CHANGED
data/lib/parsr.rb
CHANGED
@@ -3,18 +3,9 @@ require 'strscan'
|
|
3
3
|
class Parsr
|
4
4
|
|
5
5
|
BASE_PATH = File.expand_path(File.join(File.dirname(__FILE__), 'parsr'))
|
6
|
-
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :FloatRule, "#{BASE_PATH}/float_rule"
|
10
|
-
autoload :HashRule, "#{BASE_PATH}/hash_rule"
|
11
|
-
autoload :IntegerRule, "#{BASE_PATH}/integer_rule"
|
12
|
-
autoload :RangeRule, "#{BASE_PATH}/range_rule"
|
13
|
-
autoload :RawStringRule, "#{BASE_PATH}/raw_string_rule"
|
14
|
-
autoload :StringRule, "#{BASE_PATH}/string_rule"
|
15
|
-
autoload :SymbolRule, "#{BASE_PATH}/symbol_rule"
|
16
|
-
autoload :Token, "#{BASE_PATH}/token"
|
17
|
-
autoload :VERSION, "#{BASE_PATH}/version"
|
6
|
+
autoload :Rules, "#{BASE_PATH}/rules"
|
7
|
+
autoload :Token, "#{BASE_PATH}/token"
|
8
|
+
autoload :VERSION, "#{BASE_PATH}/version"
|
18
9
|
|
19
10
|
Error = Class.new(Exception)
|
20
11
|
IllegalValue = Class.new(Error)
|
@@ -49,17 +40,7 @@ class Parsr
|
|
49
40
|
class << self
|
50
41
|
|
51
42
|
def literal_eval(string)
|
52
|
-
@literal_parser ||= self.new(
|
53
|
-
ArrayRule,
|
54
|
-
HashRule,
|
55
|
-
RangeRule,
|
56
|
-
ConstantsRule,
|
57
|
-
SymbolRule,
|
58
|
-
FloatRule,
|
59
|
-
IntegerRule,
|
60
|
-
RawStringRule,
|
61
|
-
StringRule
|
62
|
-
)
|
43
|
+
@literal_parser ||= self.new(*Parsr::Rules::All)
|
63
44
|
@literal_parser.parse(string)
|
64
45
|
end
|
65
46
|
|
data/lib/parsr/rules.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Parsr::Rules
|
2
|
+
BASE_PATH = File.expand_path(File.join(File.dirname(__FILE__), 'rules'))
|
3
|
+
autoload :All, "#{BASE_PATH}/all"
|
4
|
+
autoload :Array, "#{BASE_PATH}/array"
|
5
|
+
autoload :Constants, "#{BASE_PATH}/constants"
|
6
|
+
autoload :Float, "#{BASE_PATH}/float"
|
7
|
+
autoload :Hash, "#{BASE_PATH}/hash"
|
8
|
+
autoload :Integer, "#{BASE_PATH}/integer"
|
9
|
+
autoload :Numeric, "#{BASE_PATH}/numeric"
|
10
|
+
autoload :Range, "#{BASE_PATH}/range"
|
11
|
+
autoload :Regexp, "#{BASE_PATH}/regexp"
|
12
|
+
autoload :RawString, "#{BASE_PATH}/raw_string"
|
13
|
+
autoload :String, "#{BASE_PATH}/string"
|
14
|
+
autoload :Symbol, "#{BASE_PATH}/symbol"
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Parsr::Rules
|
2
|
+
All = [
|
3
|
+
Parsr::Rules::Array,
|
4
|
+
Parsr::Rules::Hash,
|
5
|
+
Parsr::Rules::Range,
|
6
|
+
Parsr::Rules::Constants,
|
7
|
+
Parsr::Rules::Symbol,
|
8
|
+
Parsr::Rules::Float,
|
9
|
+
Parsr::Rules::Integer,
|
10
|
+
Parsr::Rules::Regexp,
|
11
|
+
Parsr::Rules::RawString,
|
12
|
+
Parsr::Rules::String
|
13
|
+
]
|
14
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Parsr::
|
1
|
+
module Parsr::Rules::Array
|
2
2
|
|
3
3
|
class Unterminated < Parsr::SyntaxError
|
4
4
|
message "unexpected '%{rest}', expecting ']'"
|
@@ -31,7 +31,7 @@ module Parsr::ArrayRule
|
|
31
31
|
|
32
32
|
def parse_unclosed_hash(scanner, token, &block)
|
33
33
|
hash = []
|
34
|
-
while pair = Parsr::
|
34
|
+
while pair = Parsr::Rules::Hash.parse_pair(scanner, token, &block)
|
35
35
|
token = nil
|
36
36
|
hash << pair
|
37
37
|
break unless scanner.scan(/\s*\,\s*/)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
module Parsr::
|
1
|
+
module Parsr::Rules::Range
|
2
2
|
|
3
|
-
NUMBER_PATTERN = Regexp.union(Parsr::
|
3
|
+
NUMBER_PATTERN = Regexp.union(Parsr::Rules::Float::PATTERN, Parsr::Rules::Integer::PATTERN)
|
4
4
|
PATTERN = /(#{NUMBER_PATTERN})(\.{2,3})(#{NUMBER_PATTERN})/
|
5
5
|
|
6
6
|
class << self
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Parsr::Rules::Regexp
|
2
|
+
|
3
|
+
OPTIONS = {
|
4
|
+
'i' => Regexp::IGNORECASE,
|
5
|
+
'm' => Regexp::MULTILINE,
|
6
|
+
'x' => Regexp::EXTENDED,
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
class Unterminated < Parsr::SyntaxError
|
10
|
+
message 'unterminated regexp meets end of file'
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
def match(scanner)
|
16
|
+
if scanner.scan(/\//)
|
17
|
+
buffer = ''
|
18
|
+
while chunk = (parse_content(scanner) || parse_escape(scanner))
|
19
|
+
buffer << chunk
|
20
|
+
end
|
21
|
+
return Parsr::Token.new(Regexp.new(buffer, parse_options(scanner)))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_content(scanner)
|
26
|
+
scanner.matched if scanner.scan(/[^\\\/]+/)
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_escape(scanner)
|
30
|
+
return scanner.matched if scanner.scan(%r{\\.})
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_options(scanner)
|
34
|
+
raise Unterminated.new(scanner) unless scanner.scan(/\/[imx]*/)
|
35
|
+
scanner.matched[1..-1].chars.map{ |o| OPTIONS[o] }.reduce(0) { |a, b| a | b }
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/parsr/version.rb
CHANGED
data/parsr.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Parsr::
|
3
|
+
describe Parsr::Rules::Float do
|
4
4
|
include_context 'rule'
|
5
5
|
|
6
6
|
describe '.match' do
|
@@ -21,6 +21,10 @@ describe Parsr::FloatRule do
|
|
21
21
|
match('-42.42').value.should be == -42.42
|
22
22
|
end
|
23
23
|
|
24
|
+
it 'should match floats with underscores for clarity' do
|
25
|
+
match('1_000.000_1').value.should be == 1_000.000_1
|
26
|
+
end
|
27
|
+
|
24
28
|
end
|
25
29
|
|
26
30
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Parsr::
|
3
|
+
describe Parsr::Rules::Integer do
|
4
4
|
include_context 'rule'
|
5
5
|
|
6
6
|
describe '.match' do
|
@@ -32,6 +32,17 @@ describe Parsr::IntegerRule do
|
|
32
32
|
result.should_not be_a(Parsr::Token)
|
33
33
|
end
|
34
34
|
|
35
|
+
it 'should match integers with containing an underscore for clarity' do
|
36
|
+
result = match('1_000')
|
37
|
+
result.should be_a Parsr::Token
|
38
|
+
result.value.should be == 1_000
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should not match integers with underscore prefix' do
|
42
|
+
result = match('_1_000')
|
43
|
+
result.should be_nil
|
44
|
+
end
|
45
|
+
|
35
46
|
end
|
36
47
|
|
37
48
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe Parsr::
|
4
|
+
describe Parsr::Rules::RawString do
|
5
5
|
include_context 'rule'
|
6
6
|
|
7
7
|
describe '.match' do
|
@@ -45,7 +45,7 @@ describe Parsr::RawStringRule do
|
|
45
45
|
it 'should raise an Parsr::RawStringRule::Unterminated if raw string is not terminated' do
|
46
46
|
expect{
|
47
47
|
match(%q{'bryan\\'s kitchen})
|
48
|
-
}.to raise_error(Parsr::
|
48
|
+
}.to raise_error(Parsr::Rules::RawString::Unterminated)
|
49
49
|
end
|
50
50
|
|
51
51
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Parsr::Rules::Regexp do
|
5
|
+
include_context 'rule'
|
6
|
+
|
7
|
+
describe '.match' do
|
8
|
+
|
9
|
+
it 'should match an empty regexp' do
|
10
|
+
match(%q{//}).value.should be == //
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should match a simple regexp' do
|
14
|
+
match(%q{/foo/}).value.should be == /foo/
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should match a regexp wth space' do
|
18
|
+
match(%q{/foo bar/}).value.should be == /foo bar/
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should match a regexp containing a backslash' do
|
22
|
+
eval(%q{ /\\\\/}).should be == /\\/
|
23
|
+
match(%q{/\\\\/}).value.should be == /\\/
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should match a regexp containing a metacharacters' do
|
27
|
+
match(%q{/\d/}).value.should be == /\d/
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should match a regexp with options' do
|
31
|
+
match(%q{/\d/ix}).value.should be == /\d/ix
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should match a regexp containing an escaped slash' do
|
35
|
+
match(%q{/\//}).value.should be == /\//
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should raise an Parsr::RegexpRule::Unterminated if regexp is not terminated' do
|
39
|
+
expect{
|
40
|
+
match(%q{/\\/})
|
41
|
+
}.to raise_error(Parsr::Rules::Regexp::Unterminated)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/spec/parsr_spec.rb
CHANGED
@@ -40,8 +40,8 @@ describe Parsr do
|
|
40
40
|
|
41
41
|
it 'should be able to parse some complexes literals' do
|
42
42
|
Parsr.literal_eval(%q{
|
43
|
-
[1, "2", foo: {egg:
|
44
|
-
}).should be == [1, "2", {:foo => {:egg =>
|
43
|
+
[1, "2", foo: {egg: /\\d+\\/\\\\/ix, 'bar,' => true}, 3 => 4.2]
|
44
|
+
}).should be == [1, "2", {:foo => {:egg => /\d+\/\\/ix, 'bar,' => true}, 3 => 4.2}]
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'should be able to parse an array included in another array' do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,100 +1,141 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: parsr
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Jean Boussier
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-01-03 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: rspec
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
22
32
|
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rake
|
23
36
|
prerelease: false
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
description: Parsr aim to provide a way to safely evaluate a ruby expression composed only with literals, just as Python's ast.literal_eval
|
49
|
+
email:
|
28
50
|
- jean.boussier@gmail.com
|
29
51
|
executables: []
|
52
|
+
|
30
53
|
extensions: []
|
54
|
+
|
31
55
|
extra_rdoc_files: []
|
32
|
-
|
56
|
+
|
57
|
+
files:
|
33
58
|
- .gitignore
|
34
59
|
- .rspec
|
60
|
+
- .travis.yml
|
35
61
|
- Gemfile
|
36
62
|
- LICENSE
|
37
63
|
- README.md
|
38
64
|
- Rakefile
|
39
65
|
- lib/parsr.rb
|
40
|
-
- lib/parsr/
|
41
|
-
- lib/parsr/
|
42
|
-
- lib/parsr/
|
43
|
-
- lib/parsr/
|
44
|
-
- lib/parsr/
|
45
|
-
- lib/parsr/
|
46
|
-
- lib/parsr/
|
47
|
-
- lib/parsr/
|
48
|
-
- lib/parsr/
|
66
|
+
- lib/parsr/rules.rb
|
67
|
+
- lib/parsr/rules/all.rb
|
68
|
+
- lib/parsr/rules/array.rb
|
69
|
+
- lib/parsr/rules/constants.rb
|
70
|
+
- lib/parsr/rules/float.rb
|
71
|
+
- lib/parsr/rules/hash.rb
|
72
|
+
- lib/parsr/rules/integer.rb
|
73
|
+
- lib/parsr/rules/numeric.rb
|
74
|
+
- lib/parsr/rules/range.rb
|
75
|
+
- lib/parsr/rules/raw_string.rb
|
76
|
+
- lib/parsr/rules/regexp.rb
|
77
|
+
- lib/parsr/rules/string.rb
|
78
|
+
- lib/parsr/rules/symbol.rb
|
49
79
|
- lib/parsr/token.rb
|
50
80
|
- lib/parsr/version.rb
|
51
81
|
- parsr.gemspec
|
52
|
-
- spec/parsr/
|
53
|
-
- spec/parsr/
|
54
|
-
- spec/parsr/
|
55
|
-
- spec/parsr/
|
56
|
-
- spec/parsr/
|
57
|
-
- spec/parsr/
|
58
|
-
- spec/parsr/
|
59
|
-
- spec/parsr/
|
60
|
-
- spec/parsr/
|
82
|
+
- spec/parsr/rules/array_spec.rb
|
83
|
+
- spec/parsr/rules/constants_spec.rb
|
84
|
+
- spec/parsr/rules/float_spec.rb
|
85
|
+
- spec/parsr/rules/hash_spec.rb
|
86
|
+
- spec/parsr/rules/integer_spec.rb
|
87
|
+
- spec/parsr/rules/range_spec.rb
|
88
|
+
- spec/parsr/rules/raw_string_spec.rb
|
89
|
+
- spec/parsr/rules/regexp_spec.rb
|
90
|
+
- spec/parsr/rules/string_spec.rb
|
91
|
+
- spec/parsr/rules/symbol_spec.rb
|
61
92
|
- spec/parsr_spec.rb
|
62
93
|
- spec/spec_helper.rb
|
63
94
|
- spec/support/rule_shared_context.rb
|
64
95
|
homepage: https://github.com/byroot/parsr/
|
65
96
|
licenses: []
|
97
|
+
|
66
98
|
post_install_message:
|
67
99
|
rdoc_options: []
|
68
|
-
|
100
|
+
|
101
|
+
require_paths:
|
69
102
|
- lib
|
70
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
104
|
none: false
|
72
|
-
requirements:
|
73
|
-
- -
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
|
76
|
-
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
113
|
none: false
|
78
|
-
requirements:
|
79
|
-
- -
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
82
121
|
requirements: []
|
122
|
+
|
83
123
|
rubyforge_project:
|
84
|
-
rubygems_version: 1.8.
|
124
|
+
rubygems_version: 1.8.10
|
85
125
|
signing_key:
|
86
126
|
specification_version: 3
|
87
127
|
summary: Simple parser to safe eval ruby literals
|
88
|
-
test_files:
|
89
|
-
- spec/parsr/
|
90
|
-
- spec/parsr/
|
91
|
-
- spec/parsr/
|
92
|
-
- spec/parsr/
|
93
|
-
- spec/parsr/
|
94
|
-
- spec/parsr/
|
95
|
-
- spec/parsr/
|
96
|
-
- spec/parsr/
|
97
|
-
- spec/parsr/
|
128
|
+
test_files:
|
129
|
+
- spec/parsr/rules/array_spec.rb
|
130
|
+
- spec/parsr/rules/constants_spec.rb
|
131
|
+
- spec/parsr/rules/float_spec.rb
|
132
|
+
- spec/parsr/rules/hash_spec.rb
|
133
|
+
- spec/parsr/rules/integer_spec.rb
|
134
|
+
- spec/parsr/rules/range_spec.rb
|
135
|
+
- spec/parsr/rules/raw_string_spec.rb
|
136
|
+
- spec/parsr/rules/regexp_spec.rb
|
137
|
+
- spec/parsr/rules/string_spec.rb
|
138
|
+
- spec/parsr/rules/symbol_spec.rb
|
98
139
|
- spec/parsr_spec.rb
|
99
140
|
- spec/spec_helper.rb
|
100
141
|
- spec/support/rule_shared_context.rb
|