rexle-xpath-parser 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 696f378210d7800f7d4c79a48d6b9b12bd641209
4
- data.tar.gz: 3118e004676a3976c4685338c469eff34c347748
3
+ metadata.gz: eab4821ed8ede5bd6583130f1b8010e6be40f006
4
+ data.tar.gz: 7020ccef47cd7f31489057b3c6a7f27749e4bc3b
5
5
  SHA512:
6
- metadata.gz: 2b3611aa3dfe406a757bdb5b14c6f5bd47dc9ab14987c4695a6ac03d0ad03c31a35d43f7e3886b26c8e31caf3fd013bb8b521323064752b81a3dc6835106d7cb
7
- data.tar.gz: 9ae85c002bee277546550dcf84520ccbf168282b85e9a087417755bcfbbbb1d0302499309736031bafa623b0372793cc968cfb216599f60b004f79b6007e51fc
6
+ metadata.gz: be752255841e13d4c23bf81b501123df2d07e6887f21d27060d21cc8b92be4fb2d4c85b3ebe48bd04a5ca00a81b67869cd0e99cabd45de31e8321afa15565249
7
+ data.tar.gz: 16804a1b8ea249903b318a4b39b4e29e6cc0b972c30dc0f073e1a0aedbe3e255728230a2110d52c63d52df51f2ddb4c97fecb647951485ff85a205f5a50b1cfd
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -7,31 +7,139 @@ class RexleXPathParser
7
7
 
8
8
  attr_reader :to_a
9
9
 
10
- def initialize(s)
11
- @to_a = scan(s.clone)
10
+ def initialize(string)
11
+
12
+ tokens = tokenise string
13
+ nested_tokens = tokens.map {|x| scan(x)}
14
+ @to_a = functionalise nested_tokens
15
+
12
16
  end
13
17
 
14
- def scan(s2)
18
+ private
19
+
20
+ # maps the nested tokens to XPath functions, predicates, operators,
21
+ # and 1 or more elements
22
+ #
23
+ def functionalise(a)
15
24
 
16
- if s2.lstrip[0] == '|' then
17
- return [s2.slice!(/\s*\|\s*/).strip]
25
+ a.map do |x|
26
+
27
+ if x =~ /\w+\[/ then
28
+ epath, predicate = x.match(/^([^\[]+)\[([^\]]+)\]/).captures
29
+ epath.split('/').map {|e| [:select, e]} + [:predicate, predicate]
30
+ elsif x =~ /\|/
31
+ [:union]
32
+ elsif x =~ /\w+\(/
33
+ [x.chop.to_sym]
34
+ elsif x =~ /\d+/
35
+ [:index, x[1..-2]]
36
+ elsif x =~ /[\w\/]+/
37
+ x.split('/').map {|e| [:select, e]}
38
+ elsif x.is_a? Array
39
+ functionalise(x)
40
+ end
41
+
18
42
  end
19
43
 
20
- s1 = s2.slice!(/\w+[\(\[]/)
44
+ end
45
+
46
+ # matches a left bracket with a right bracket recursively if necessary
47
+ #
48
+ def lmatch(a, lchar, rchar)
49
+
50
+ token = []
51
+ c = a.first
52
+ token << c until (c = a.shift; c == lchar or c == rchar or a.empty?)
53
+ token << c
21
54
 
22
- if s1[-1] == '[' then
23
- s1 << s2.slice!(/[^\]]+\]|\]/)
24
- return [s1]
55
+ if c == lchar then
56
+ found, tokenx, remainderx = rmatch(a, lchar, rchar)
57
+ c = found
58
+ token << tokenx
59
+ remainder = remainderx
60
+ else
61
+ remainder = a.join
25
62
  end
26
63
 
27
- if s2[/\w+[\(\[]/] then
28
- r = [scan(s2)]
29
- r << scan(s2) while s2[/\w+[\(\[]/]
30
- s3 = s2
64
+ [c, token.join, remainder]
65
+ end
66
+
67
+ # tokeniser e.g. "a | d(c)" #=> ["a", " | ", "d(c)"]
68
+ #
69
+ def match(s)
70
+
71
+ a = []
72
+
73
+ if s =~ /^\w+\(/ then
74
+
75
+ found, token, remainder = lmatch(s.chars, '(',')')
76
+
77
+ if found == ')' then
78
+ a << token
79
+ end
80
+
81
+ elsif s =~ /^\w+\[/
82
+ found, token, remainder = lmatch(s.chars, '[',']')
83
+ a << token
31
84
  else
32
- s1 << s2.slice!(/[^\)\]]+[\)\]]|[\)\]]/)
85
+ token = s.slice!(/\w+/)
86
+ a << token
87
+ remainder = s
88
+ end
89
+
90
+ operator = remainder.slice!(/^\s*\|\s*/)
91
+
92
+ if operator then
93
+ a.concat [operator, *match(remainder)]
94
+ end
95
+
96
+ a
97
+ end
98
+
99
+ # matches a right bracket for a left bracket which has already been found.
100
+ #
101
+ def rmatch(a, lchar, rchar)
102
+
103
+ token = []
104
+ c = a.first
105
+ token << c until (c = a.shift; c == lchar or c == rchar or a.empty?)
106
+ token << c
107
+
108
+ if c == lchar then
109
+
110
+ found, tokenx, remainderx = rmatch(a, lchar, rchar)
111
+ token << tokenx
112
+
113
+ # find the rmatch for the starting token
114
+ found, tokenx, remainderx = rmatch(a, lchar, rchar)
115
+ c = found
116
+ token << tokenx
117
+ remainder = remainderx
118
+
119
+ elsif c = rchar
120
+ remainder = a.join
33
121
  end
34
122
 
35
- [s1,r,s3].compact
123
+ [c, token.join, remainder]
36
124
  end
37
- end
125
+
126
+ # accepts a token and drills into it to identify more tokens beneath it
127
+ #
128
+ def scan(s)
129
+
130
+ if s =~ /^\w+\(/ then
131
+ func = s.slice!(/\w+\(/)
132
+ remainder = s[0..-2]
133
+ if remainder =~ /^\w+\(/ then
134
+ scan(remainder)
135
+ else
136
+ [func, match(remainder)]
137
+ end
138
+ else
139
+ s
140
+ end
141
+ end
142
+
143
+ alias tokenise match
144
+
145
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rexle-xpath-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -31,7 +31,7 @@ cert_chain:
31
31
  adFNS7+S3VVpQqBQ7hIMoNW5ldGHINll6Z0dbjsCO8OFGOkrnzt9ovLffOXuQHpT
32
32
  Gpk2If0KQMuV2Q==
33
33
  -----END CERTIFICATE-----
34
- date: 2015-05-29 00:00:00.000000000 Z
34
+ date: 2015-06-04 00:00:00.000000000 Z
35
35
  dependencies: []
36
36
  description:
37
37
  email: james@r0bertson.co.uk
metadata.gz.sig CHANGED
Binary file