jgrep 1.4.1 → 1.5.0
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 +4 -4
- data/CHANGELOG.markdown +5 -0
- data/README.markdown +13 -12
- data/Rakefile +6 -1
- data/bin/jgrep +115 -129
- data/lib/jgrep.rb +286 -377
- data/lib/parser/parser.rb +109 -125
- data/lib/parser/scanner.rb +148 -149
- data/spec/Rakefile +3 -3
- data/spec/spec_helper.rb +1 -2
- data/spec/unit/jgrep_spec.rb +233 -233
- data/spec/unit/parser_spec.rb +132 -127
- data/spec/unit/scanner_spec.rb +82 -86
- metadata +6 -18
data/spec/unit/parser_spec.rb
CHANGED
@@ -1,132 +1,137 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
4
2
|
|
5
3
|
module JGrep
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
4
|
+
describe Parser do
|
5
|
+
describe "#parse" do
|
6
|
+
it "should parse statements seperated by '='" do
|
7
|
+
parser = Parser.new("foo.bar=bar")
|
8
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar=bar"}])
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should parse statements seperated by '<'" do
|
12
|
+
parser = Parser.new("foo.bar<1")
|
13
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar<1"}])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should parse statements seperated by '>'" do
|
17
|
+
parser = Parser.new("foo.bar>1")
|
18
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar>1"}])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should parse statements seperated by '<='" do
|
22
|
+
parser = Parser.new("foo.bar<=1")
|
23
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar<=1"}])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should parse statements seperated by '>='" do
|
27
|
+
parser = Parser.new("foo.bar>=1")
|
28
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar>=1"}])
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse statement sperated by '!='" do
|
32
|
+
parser = Parser.new("foo.bar!=1")
|
33
|
+
expect(parser.execution_stack).to eq([{"not" => "not"}, {"statement" => "foo.bar=1"}])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should parse a + token" do
|
37
|
+
parser = Parser.new("+foo")
|
38
|
+
expect(parser.execution_stack).to eq([{"+" => "foo"}])
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should parse a - token" do
|
42
|
+
parser = Parser.new("-foo")
|
43
|
+
expect(parser.execution_stack).to eq([{"-" => "foo"}])
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should parse a correct 'and' token" do
|
47
|
+
parser = Parser.new("foo.bar=123 and bar.foo=321")
|
48
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar=123"}, {"and" => "and"}, {"statement" => "bar.foo=321"}])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not parse an incorrect and token" do
|
52
|
+
expect do
|
53
|
+
Parser.new("and foo.bar=1")
|
54
|
+
end.to raise_error("Error at column 12. \n Expression cannot start with 'and'")
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should parse a correct 'or' token" do
|
58
|
+
parser = Parser.new("foo.bar=1 or bar.foo=1")
|
59
|
+
expect(parser.execution_stack).to eq([{"statement" => "foo.bar=1"}, {"or" => "or"}, {"statement" => "bar.foo=1"}])
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should not parse an incorrect and token" do
|
63
|
+
expect do
|
64
|
+
Parser.new("or foo.bar=1")
|
65
|
+
end.to raise_error("Error at column 11. \n Expression cannot start with 'or'")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should parse a correct 'not' token" do
|
69
|
+
parser = Parser.new("! bar.foo=1")
|
70
|
+
expect(parser.execution_stack).to eq([{"not" => "not"}, {"statement" => "bar.foo=1"}])
|
71
|
+
parser = Parser.new("not bar.foo=1")
|
72
|
+
expect(parser.execution_stack).to eq([{"not" => "not"}, {"statement" => "bar.foo=1"}])
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should not parse an incorrect 'not' token" do
|
76
|
+
expect do
|
77
|
+
Parser.new("foo.bar=1 !")
|
78
|
+
end.to raise_error("Error at column 10. \nExpected 'and', 'or', ')'. Found 'not'")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should parse correct parentheses" do
|
82
|
+
parser = Parser.new("(foo.bar=1)")
|
83
|
+
expect(parser.execution_stack).to eq([{"(" => "("}, {"statement" => "foo.bar=1"}, {")" => ")"}])
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should fail on incorrect parentheses" do
|
87
|
+
expect do
|
88
|
+
Parser.new(")foo.bar=1(")
|
89
|
+
end.to raise_error("Error. Missing parentheses '('.")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should fail on missing parentheses" do
|
93
|
+
expect do
|
94
|
+
Parser.new("(foo.bar=1")
|
95
|
+
end.to raise_error("Error. Missing parentheses ')'.")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should parse correctly formatted compound statements" do
|
99
|
+
parser = Parser.new("(foo.bar=1 or foo.rab=1) and (bar.foo=1)")
|
100
|
+
expect(parser.execution_stack).to eq([{"(" => "("}, {"statement" => "foo.bar=1"}, {"or" => "or"}, {"statement" => "foo.rab=1"},
|
101
|
+
{")" => ")"}, {"and" => "and"}, {"(" => "("}, {"statement" => "bar.foo=1"},
|
102
|
+
{")" => ")"}])
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should parse complex array statements" do
|
106
|
+
parser = Parser.new("[foo.bar=1]")
|
107
|
+
expect(parser.execution_stack).to eq([{"statement" => [["statement", "foo.bar=1"]]}])
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should not parse failed complex array statements" do
|
111
|
+
expect do
|
112
|
+
Parser.new("[foo.bar=1 or]")
|
113
|
+
end.to raise_error("Class name cannot be 'and', 'or', 'not'. Found 'or'")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should not allow nested complex array statements" do
|
117
|
+
expect do
|
118
|
+
Parser.new("[foo.bar=1 and [foo.bar=1]]")
|
119
|
+
end.to raise_error("Error at column 27\nError, cannot define '[' in a '[...]' block.")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should parse complex, compound array statements" do
|
123
|
+
parser = Parser.new("[foo.bar=1 and foo.rab=2] and !(foo=1)")
|
124
|
+
expect(parser.execution_stack).to eq(
|
125
|
+
[
|
126
|
+
{"statement" => [["statement", "foo.bar=1"], %w[and and], ["statement", "foo.rab=2"]]},
|
127
|
+
{"and" => "and"},
|
128
|
+
{"not" => "not"},
|
129
|
+
{"(" => "("},
|
130
|
+
{"statement" => "foo=1"},
|
131
|
+
{")" => ")"}
|
132
|
+
]
|
133
|
+
)
|
134
|
+
end
|
131
135
|
end
|
136
|
+
end
|
132
137
|
end
|
data/spec/unit/scanner_spec.rb
CHANGED
@@ -1,91 +1,87 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
4
2
|
|
5
|
-
|
6
3
|
module JGrep
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
end
|
89
|
-
end
|
4
|
+
describe Scanner do
|
5
|
+
describe "#get_token" do
|
6
|
+
it "should identify a '(' token" do
|
7
|
+
scanner = Scanner.new("(")
|
8
|
+
token = scanner.get_token
|
9
|
+
expect(token).to eq(["(", "("])
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should identify a ')' token" do
|
13
|
+
scanner = Scanner.new(")")
|
14
|
+
token = scanner.get_token
|
15
|
+
expect(token).to eq([")", ")"])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should identify an 'and' token" do
|
19
|
+
scanner = Scanner.new("and ")
|
20
|
+
token = scanner.get_token
|
21
|
+
expect(token).to eq(%w[and and])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should identify a '&&' token" do
|
25
|
+
scanner = Scanner.new("&& ")
|
26
|
+
token = scanner.get_token
|
27
|
+
expect(token).to eq(%w[and and])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should identify an 'or' token" do
|
31
|
+
scanner = Scanner.new("or ")
|
32
|
+
token = scanner.get_token
|
33
|
+
expect(token).to eq(%w[or or])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should identify a " || " token" do
|
37
|
+
scanner = Scanner.new("|| ")
|
38
|
+
token = scanner.get_token
|
39
|
+
expect(token).to eq(%w[or or])
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should identify an 'not' token" do
|
43
|
+
scanner = Scanner.new("not ")
|
44
|
+
token = scanner.get_token
|
45
|
+
expect(token).to eq(%w[not not])
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should identify an '!' token" do
|
49
|
+
scanner = Scanner.new("!")
|
50
|
+
token = scanner.get_token
|
51
|
+
expect(token).to eq(%w[not not])
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should identify a statement token" do
|
55
|
+
scanner = Scanner.new("foo.bar=bar")
|
56
|
+
token = scanner.get_token
|
57
|
+
expect(token).to eq(["statement", "foo.bar=bar"])
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should identify a complex array statement" do
|
61
|
+
scanner = Scanner.new("[foo=bar and bar=foo]")
|
62
|
+
token = scanner.get_token
|
63
|
+
expect(token).to eq(["statement", [["statement", "foo=bar"], %w[and and], ["statement", "bar=foo"]]])
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should fail if expression terminates with 'and'" do
|
67
|
+
scanner = Scanner.new("and")
|
68
|
+
|
69
|
+
expect do
|
70
|
+
scanner.get_token
|
71
|
+
end.to raise_error("Class name cannot be 'and', 'or', 'not'. Found 'and'")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should identify a '+' token" do
|
75
|
+
scanner = Scanner.new("+foo")
|
76
|
+
token = scanner.get_token
|
77
|
+
expect(token).to eq(["+", "foo"])
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should identify a '-' token" do
|
81
|
+
scanner = Scanner.new("-foo")
|
82
|
+
token = scanner.get_token
|
83
|
+
expect(token).to eq(["-", "foo"])
|
84
|
+
end
|
90
85
|
end
|
86
|
+
end
|
91
87
|
end
|
metadata
CHANGED
@@ -1,35 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jgrep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- P Loubser
|
8
8
|
- Dominic Cleal
|
9
|
+
- R.I. Pienaar
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: json
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '0'
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: '0'
|
13
|
+
date: 2017-08-09 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
28
15
|
description: Compare a list of json documents to a simple logical language and returns
|
29
16
|
matches as output
|
30
17
|
email:
|
31
18
|
- ploubser@gmail.com
|
32
19
|
- dominic@cleal.org
|
20
|
+
- rip@devco.net
|
33
21
|
executables:
|
34
22
|
- jgrep
|
35
23
|
extensions: []
|
@@ -70,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
58
|
version: '0'
|
71
59
|
requirements: []
|
72
60
|
rubyforge_project:
|
73
|
-
rubygems_version: 2.
|
61
|
+
rubygems_version: 2.5.1
|
74
62
|
signing_key:
|
75
63
|
specification_version: 4
|
76
64
|
summary: Filter JSON documents with a simple logical language
|