query-ruby 0.1.0 → 1.1.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/Gemfile.lock +1 -1
- data/VERSION +1 -1
- data/bin/query +2 -2
- data/lib/query/combiner.rb +8 -10
- data/lib/query/decompiler.rb +19 -3
- data/lib/query/node/base_10.rb +3 -6
- data/lib/query/node/boolean.rb +1 -1
- data/lib/query/node/decimal.rb +1 -1
- data/lib/query/node/operator.rb +8 -5
- data/lib/query/node/query.rb +61 -3
- data/lib/query/parser/boolean.rb +4 -8
- data/lib/query/parser/group.rb +12 -0
- data/lib/query/parser/key.rb +1 -1
- data/lib/query/parser/key_value.rb +1 -3
- data/lib/query/parser/logic_operator.rb +21 -0
- data/lib/query/parser/not_operator.rb +11 -0
- data/lib/query/parser/number.rb +1 -5
- data/lib/query/parser/operator.rb +27 -30
- data/lib/query/parser/part.rb +4 -1
- data/lib/query/parser/query.rb +1 -5
- data/lib/query/parser/range.rb +5 -8
- data/lib/query/parser/special.rb +12 -0
- data/lib/query/parser/statement.rb +13 -0
- data/lib/query/parser/string.rb +2 -6
- data/lib/query/parser/value.rb +1 -1
- data/spec/query_spec.rb +6 -3
- metadata +7 -5
- data/lib/query/node/part.rb +0 -21
- data/lib/query/node/text.rb +0 -17
- data/lib/query/parser/text.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 637f0d62e9d40ea882160cc00f8e10fd09cb2ad730387c29d2170a07150ff894
|
4
|
+
data.tar.gz: f4617293cd65815243117e7d939a7b98102da0c2c4d77c7dd692e2b1618c1187
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c46fea9d0bad92f106400380c9b095746141b5eb312970b26a15cbb2b39010b4e5a4d6738ed6e3f3e2dfd4a4cb94ab1e2451ccba2da9270818ca1140a170c3c
|
7
|
+
data.tar.gz: 62519e0608c41d5b3348822380ca50ef3b501c5561aa0067a1f325029a210a79fa4e1eb9432ef47fc553712a06c414e6a035233e1f1f5697b9a2d45ce38ff3de
|
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
1.1.0
|
data/bin/query
CHANGED
@@ -35,14 +35,14 @@ parsed =
|
|
35
35
|
abort Query::Version.to_s if parsed.options.version
|
36
36
|
abort parsed.help if parsed.options.help
|
37
37
|
|
38
|
-
inputs = [parsed.options.input.to_s]
|
38
|
+
inputs = [parsed.options.input.to_s].compact_blank
|
39
39
|
inputs += parsed.arguments
|
40
40
|
inputs += parsed.files.map { |file| File.read(file) }
|
41
41
|
|
42
42
|
input = inputs.join(" ")
|
43
43
|
|
44
44
|
if parsed.options.parse
|
45
|
-
pp Query
|
45
|
+
pp Query.parse(input)
|
46
46
|
elsif parsed.options.decompile
|
47
47
|
puts Query.decompile(Query.evaluate(input))
|
48
48
|
elsif parsed.options.combine
|
data/lib/query/combiner.rb
CHANGED
@@ -11,13 +11,10 @@ class Query
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def combine
|
14
|
-
sources
|
15
|
-
Query.evaluate(source)
|
16
|
-
|
17
|
-
|
18
|
-
end.then do |parsed|
|
19
|
-
Query.decompile(parsed)
|
20
|
-
end
|
14
|
+
sources
|
15
|
+
.map { |source| Query.evaluate(source) }
|
16
|
+
.reduce { |acc, element| combine_parsed(acc, element) }
|
17
|
+
.then { |parsed| Query.decompile(parsed) }
|
21
18
|
end
|
22
19
|
|
23
20
|
private
|
@@ -25,9 +22,10 @@ class Query
|
|
25
22
|
attr_accessor :sources
|
26
23
|
|
27
24
|
def combine_parsed(left, right)
|
28
|
-
(left + right)
|
29
|
-
|
30
|
-
|
25
|
+
(left + right)
|
26
|
+
.reverse
|
27
|
+
.uniq { |node| node.is_a?(Hash) ? [node[:key], node[:operator]] : node }
|
28
|
+
.reverse
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
data/lib/query/decompiler.rb
CHANGED
@@ -11,17 +11,33 @@ class Query
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def decompile
|
14
|
-
parsed.
|
14
|
+
if parsed.is_a?(Hash) && parsed.key?(:left)
|
15
|
+
format_logic_operator(parsed)
|
16
|
+
elsif parsed.is_a?(Hash) && parsed.key?(:right)
|
17
|
+
format_not_operator(parsed)
|
18
|
+
else
|
19
|
+
format_value(parsed)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_logic_operator(parsed)
|
24
|
+
left = self.class.decompile(parsed[:left])
|
25
|
+
right = self.class.decompile(parsed[:right])
|
26
|
+
|
27
|
+
"(#{left} #{parsed[:operator]} #{right})"
|
15
28
|
end
|
16
29
|
|
17
|
-
def
|
30
|
+
def format_not_operator(parsed)
|
31
|
+
right = self.class.decompile(parsed[:right])
|
32
|
+
|
33
|
+
"(#{parsed[:operator]} #{right})"
|
18
34
|
end
|
19
35
|
|
20
36
|
def format_value(value)
|
21
37
|
if value.is_a?(Hash)
|
22
38
|
"#{value[:key]}#{value[:operator]}#{format_value(value[:value])}"
|
23
39
|
elsif value.is_a?(String)
|
24
|
-
Query.evaluate(value).
|
40
|
+
Query.evaluate(value).is_a?(Hash) ? value.inspect : value
|
25
41
|
elsif value.is_a?(BigDecimal)
|
26
42
|
value.to_s("F")
|
27
43
|
elsif value.is_a?(Range)
|
data/lib/query/node/base_10.rb
CHANGED
@@ -7,15 +7,12 @@ class Query
|
|
7
7
|
|
8
8
|
def initialize(parsed)
|
9
9
|
self.whole = parsed.delete(:whole)
|
10
|
-
self.exponent =
|
10
|
+
self.exponent =
|
11
|
+
Node::Value.new(parsed.delete(:exponent)) if parsed.key?(:exponent)
|
11
12
|
end
|
12
13
|
|
13
14
|
def evaluate(**args)
|
14
|
-
|
15
|
-
whole.to_i * 10 ** exponent.evaluate(**args)
|
16
|
-
else
|
17
|
-
whole.to_i
|
18
|
-
end
|
15
|
+
exponent ? whole.to_i * 10**exponent.evaluate(**args) : whole.to_i
|
19
16
|
end
|
20
17
|
end
|
21
18
|
end
|
data/lib/query/node/boolean.rb
CHANGED
data/lib/query/node/decimal.rb
CHANGED
data/lib/query/node/operator.rb
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
class Query
|
4
4
|
class Node
|
5
5
|
class Operator < Node
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :prefix, :suffix
|
7
7
|
|
8
|
-
|
8
|
+
PREFIXES = { "+" => "", "-" => "!", "!" => "!", "" => "", nil => "" }
|
9
|
+
|
10
|
+
SUFFIXES = {
|
9
11
|
"^" => "^",
|
10
12
|
"$" => "$",
|
11
13
|
">=" => ">=",
|
@@ -20,15 +22,16 @@ class Query
|
|
20
22
|
":" => ":",
|
21
23
|
"=" => "=",
|
22
24
|
"==" => "=",
|
23
|
-
"===" => "="
|
25
|
+
"===" => "="
|
24
26
|
}
|
25
27
|
|
26
28
|
def initialize(parsed)
|
27
|
-
self.
|
29
|
+
self.prefix = parsed.delete(:prefix)
|
30
|
+
self.suffix = parsed.delete(:suffix)
|
28
31
|
end
|
29
32
|
|
30
33
|
def evaluate(**args)
|
31
|
-
|
34
|
+
"#{PREFIXES.fetch(prefix)}#{SUFFIXES.fetch(suffix)}"
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
data/lib/query/node/query.rb
CHANGED
@@ -3,14 +3,72 @@
|
|
3
3
|
class Query
|
4
4
|
class Node
|
5
5
|
class Query < Node
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :left, :operator, :right, :query, :negative
|
7
|
+
|
8
|
+
LOGIC_OPERATORS = {
|
9
|
+
"or" => "or",
|
10
|
+
"Or" => "or",
|
11
|
+
"OR" => "or",
|
12
|
+
"||" => "or",
|
13
|
+
"|" => "or",
|
14
|
+
"and" => "and",
|
15
|
+
"And" => "and",
|
16
|
+
"AND" => "and",
|
17
|
+
"&&" => "and",
|
18
|
+
"&" => "and",
|
19
|
+
"" => "and",
|
20
|
+
nil => "and"
|
21
|
+
}
|
22
|
+
|
23
|
+
NEGATIVE_OPERATORS = {
|
24
|
+
"not" => "not",
|
25
|
+
"Not" => "not",
|
26
|
+
"NOT" => "not",
|
27
|
+
"!" => "not"
|
28
|
+
}
|
7
29
|
|
8
30
|
def initialize(parsed)
|
9
|
-
self.
|
31
|
+
self.negative = (parsed.presence || {}).delete(:not)
|
32
|
+
|
33
|
+
if parsed.is_a?(Hash)
|
34
|
+
if parsed.key?(:key_value)
|
35
|
+
self.query = KeyValue.new(parsed.delete(:key_value))
|
36
|
+
elsif parsed.key?(:string)
|
37
|
+
self.query = String.new(parsed.delete(:string))
|
38
|
+
else
|
39
|
+
self.left = Query.new(parsed.delete(:left))
|
40
|
+
self.operator = parsed.delete(:operator)
|
41
|
+
self.right = Query.new(parsed.delete(:right))
|
42
|
+
end
|
43
|
+
else
|
44
|
+
self.query = String.new(parsed)
|
45
|
+
end
|
10
46
|
end
|
11
47
|
|
12
48
|
def evaluate(**args)
|
13
|
-
|
49
|
+
if negative && query
|
50
|
+
{
|
51
|
+
operator: NEGATIVE_OPERATORS.fetch(negative),
|
52
|
+
right: query.evaluate(**args)
|
53
|
+
}
|
54
|
+
elsif negative
|
55
|
+
{
|
56
|
+
operator: NEGATIVE_OPERATORS.fetch(negative),
|
57
|
+
right: {
|
58
|
+
left: left.evaluate(**args),
|
59
|
+
operator: LOGIC_OPERATORS.fetch(operator),
|
60
|
+
right: right.evaluate(**args)
|
61
|
+
}
|
62
|
+
}
|
63
|
+
elsif query
|
64
|
+
query.evaluate(**args)
|
65
|
+
else
|
66
|
+
{
|
67
|
+
left: left.evaluate(**args),
|
68
|
+
operator: LOGIC_OPERATORS.fetch(operator),
|
69
|
+
right: right.evaluate(**args)
|
70
|
+
}
|
71
|
+
end
|
14
72
|
end
|
15
73
|
end
|
16
74
|
end
|
data/lib/query/parser/boolean.rb
CHANGED
@@ -3,20 +3,16 @@
|
|
3
3
|
class Query
|
4
4
|
class Parser
|
5
5
|
class Boolean < Language
|
6
|
-
def special
|
7
|
-
str("...") | str("..") | Whitespace | Operator
|
8
|
-
end
|
9
|
-
|
10
6
|
def root
|
11
7
|
(
|
12
8
|
(
|
13
9
|
str("true") | str("t") | str("True") | str("TRUE") | str("T") |
|
14
10
|
str("yes") | str("y") | str("Yes") | str("YES") | str("Y") |
|
15
11
|
str("on") | str("On") | str("ON")
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
) <<
|
12
|
+
str("false") | str("f") | str("False") | str("FALSE") | str("F") |
|
13
|
+
str("no") | str("n") | str("No") | str("NO") | str("N") |
|
14
|
+
str("off") | str("Off") | str("OFF")
|
15
|
+
) << Special.present
|
20
16
|
).aka(:boolean)
|
21
17
|
end
|
22
18
|
end
|
data/lib/query/parser/key.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Query
|
4
|
+
class Parser
|
5
|
+
class LogicOperator < Language
|
6
|
+
def root
|
7
|
+
(
|
8
|
+
Whitespace << (
|
9
|
+
str("and") | str("And") | str("AND") | str("or") | str("Or") |
|
10
|
+
str("OR")
|
11
|
+
) << Whitespace
|
12
|
+
) |
|
13
|
+
(
|
14
|
+
Whitespace.maybe << (
|
15
|
+
str("&&") | str("&") | str("||") | str("|") | str("")
|
16
|
+
) << Whitespace.maybe
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/query/parser/number.rb
CHANGED
@@ -3,10 +3,6 @@
|
|
3
3
|
class Query
|
4
4
|
class Parser
|
5
5
|
class Number < Language
|
6
|
-
def special
|
7
|
-
str("...") | str("..") | Whitespace | Operator
|
8
|
-
end
|
9
|
-
|
10
6
|
def zero
|
11
7
|
str("0")
|
12
8
|
end
|
@@ -150,7 +146,7 @@ class Query
|
|
150
146
|
decimal.aka(:decimal) | base_16_number.aka(:base_16) |
|
151
147
|
base_8_number.aka(:base_8) | base_2_number.aka(:base_2) |
|
152
148
|
base_10_number.aka(:base_10)
|
153
|
-
) <<
|
149
|
+
) << Special.present
|
154
150
|
).aka(:number)
|
155
151
|
end
|
156
152
|
end
|
@@ -3,39 +3,36 @@
|
|
3
3
|
class Query
|
4
4
|
class Parser
|
5
5
|
class Operator < Language
|
6
|
-
|
7
|
-
"^",
|
8
|
-
"$",
|
9
|
-
">=",
|
10
|
-
"=>",
|
11
|
-
"<=",
|
12
|
-
"=<",
|
13
|
-
"<",
|
14
|
-
">",
|
15
|
-
"!",
|
16
|
-
]
|
6
|
+
PREFIXES = %w[- + !]
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
":",
|
22
|
-
"===",
|
23
|
-
"==",
|
24
|
-
"=",
|
25
|
-
"",
|
26
|
-
]
|
8
|
+
OPERATORS = %w[^ $ >= => <= =< < > !]
|
9
|
+
|
10
|
+
MODIFIERS = [":::", "::", ":", "===", "==", "=", ""]
|
27
11
|
|
28
12
|
def root
|
29
|
-
|
30
|
-
|
31
|
-
str(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
13
|
+
(
|
14
|
+
PREFIXES
|
15
|
+
.map { |prefix| str(prefix) }
|
16
|
+
.reduce(&:|)
|
17
|
+
.aka(:prefix)
|
18
|
+
.maybe << (
|
19
|
+
OPERATORS
|
20
|
+
.flat_map do |operator|
|
21
|
+
MODIFIERS
|
22
|
+
.map do |modifier|
|
23
|
+
str("#{operator}#{modifier}") |
|
24
|
+
str("#{modifier}#{operator}") | str(operator)
|
25
|
+
end
|
26
|
+
.reduce(&:|)
|
27
|
+
.then { operator }
|
28
|
+
end
|
29
|
+
.reduce(&:|) |
|
30
|
+
MODIFIERS
|
31
|
+
.compact_blank
|
32
|
+
.map { |modifier| str(modifier) }
|
33
|
+
.reduce(&:|)
|
34
|
+
).aka(:suffix)
|
35
|
+
).aka(:operator)
|
39
36
|
end
|
40
37
|
end
|
41
38
|
end
|
data/lib/query/parser/part.rb
CHANGED
data/lib/query/parser/query.rb
CHANGED
@@ -3,12 +3,8 @@
|
|
3
3
|
class Query
|
4
4
|
class Parser
|
5
5
|
class Query < Language
|
6
|
-
def whitespace?
|
7
|
-
Whitespace.maybe
|
8
|
-
end
|
9
|
-
|
10
6
|
def root
|
11
|
-
|
7
|
+
Whitespace.maybe << Part.maybe << Whitespace.maybe
|
12
8
|
end
|
13
9
|
end
|
14
10
|
end
|
data/lib/query/parser/range.rb
CHANGED
@@ -11,20 +11,17 @@ class Query
|
|
11
11
|
Whitespace.maybe
|
12
12
|
end
|
13
13
|
|
14
|
-
def special
|
15
|
-
str("...") | str("..") | Whitespace | Operator
|
16
|
-
end
|
17
|
-
|
18
14
|
def root
|
19
15
|
(
|
20
16
|
(
|
21
17
|
(
|
22
18
|
Number.aka(:left) << operator.aka(:operator) << Number.aka(:right)
|
23
19
|
) |
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
(
|
21
|
+
String.aka(:left) << operator.aka(:operator) <<
|
22
|
+
String.aka(:right)
|
23
|
+
)
|
24
|
+
) << Special.present
|
28
25
|
).aka(:range)
|
29
26
|
end
|
30
27
|
end
|
data/lib/query/parser/string.rb
CHANGED
@@ -15,10 +15,6 @@ class Query
|
|
15
15
|
str("\\")
|
16
16
|
end
|
17
17
|
|
18
|
-
def special
|
19
|
-
str("...") | str("..") | Whitespace | Operator
|
20
|
-
end
|
21
|
-
|
22
18
|
def double_quoted_string
|
23
19
|
double_quote.ignore << (
|
24
20
|
(backslash.ignore << double_quote) | (double_quote.absent << any)
|
@@ -35,8 +31,8 @@ class Query
|
|
35
31
|
(
|
36
32
|
(
|
37
33
|
double_quoted_string | single_quoted_string |
|
38
|
-
(
|
39
|
-
) <<
|
34
|
+
(Special.absent << any).repeat(1)
|
35
|
+
) << Special.present
|
40
36
|
).aka(:string)
|
41
37
|
end
|
42
38
|
end
|
data/lib/query/parser/value.rb
CHANGED
data/spec/query_spec.rb
CHANGED
@@ -57,15 +57,18 @@ RSpec.describe Query do
|
|
57
57
|
"verified:f",
|
58
58
|
"verified:off",
|
59
59
|
"verified:no",
|
60
|
+
"a b",
|
61
|
+
"a or b",
|
62
|
+
"a:1 or b",
|
63
|
+
"a:1 or b:2..3",
|
64
|
+
"(a or b) and (not b ! c)"
|
60
65
|
].each do |source|
|
61
66
|
it source.inspect do
|
62
67
|
Query.evaluate(source)
|
63
68
|
end
|
64
69
|
|
65
70
|
it "decompiles #{source.inspect}" do
|
66
|
-
expect(
|
67
|
-
Query.evaluate(Query.decompile(Query.evaluate(source)))
|
68
|
-
).to eq(
|
71
|
+
expect(Query.evaluate(Query.decompile(Query.evaluate(source)))).to eq(
|
69
72
|
Query.evaluate(source)
|
70
73
|
)
|
71
74
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: query-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dorian Marié
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-28 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activesupport
|
@@ -132,23 +132,25 @@ files:
|
|
132
132
|
- lib/query/node/key_value.rb
|
133
133
|
- lib/query/node/number.rb
|
134
134
|
- lib/query/node/operator.rb
|
135
|
-
- lib/query/node/part.rb
|
136
135
|
- lib/query/node/query.rb
|
137
136
|
- lib/query/node/range.rb
|
138
137
|
- lib/query/node/string.rb
|
139
|
-
- lib/query/node/text.rb
|
140
138
|
- lib/query/node/value.rb
|
141
139
|
- lib/query/parser.rb
|
142
140
|
- lib/query/parser/boolean.rb
|
141
|
+
- lib/query/parser/group.rb
|
143
142
|
- lib/query/parser/key.rb
|
144
143
|
- lib/query/parser/key_value.rb
|
144
|
+
- lib/query/parser/logic_operator.rb
|
145
|
+
- lib/query/parser/not_operator.rb
|
145
146
|
- lib/query/parser/number.rb
|
146
147
|
- lib/query/parser/operator.rb
|
147
148
|
- lib/query/parser/part.rb
|
148
149
|
- lib/query/parser/query.rb
|
149
150
|
- lib/query/parser/range.rb
|
151
|
+
- lib/query/parser/special.rb
|
152
|
+
- lib/query/parser/statement.rb
|
150
153
|
- lib/query/parser/string.rb
|
151
|
-
- lib/query/parser/text.rb
|
152
154
|
- lib/query/parser/value.rb
|
153
155
|
- lib/query/parser/whitespace.rb
|
154
156
|
- lib/query/version.rb
|
data/lib/query/node/part.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Query
|
4
|
-
class Node
|
5
|
-
class Part < Node
|
6
|
-
attr_accessor :part
|
7
|
-
|
8
|
-
def initialize(parsed)
|
9
|
-
if parsed.key?(:key_value)
|
10
|
-
self.part = KeyValue.new(parsed.delete(:key_value))
|
11
|
-
elsif parsed.key?(:text)
|
12
|
-
self.part = Text.new(parsed.delete(:text))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def evaluate(**args)
|
17
|
-
part&.evaluate(**args)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/query/node/text.rb
DELETED
data/lib/query/parser/text.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Query
|
4
|
-
class Parser
|
5
|
-
class Text < Language
|
6
|
-
def double_quote
|
7
|
-
str('"')
|
8
|
-
end
|
9
|
-
|
10
|
-
def single_quote
|
11
|
-
str("'")
|
12
|
-
end
|
13
|
-
|
14
|
-
def backslash
|
15
|
-
str("\\")
|
16
|
-
end
|
17
|
-
|
18
|
-
def double_quoted_string
|
19
|
-
double_quote.ignore << (
|
20
|
-
(backslash.ignore << double_quote) | (double_quote.absent << any)
|
21
|
-
).repeat << double_quote.maybe.ignore
|
22
|
-
end
|
23
|
-
|
24
|
-
def single_quoted_string
|
25
|
-
single_quote.ignore << (
|
26
|
-
(backslash.ignore << single_quote) | (single_quote.absent << any)
|
27
|
-
).repeat << single_quote.maybe.ignore
|
28
|
-
end
|
29
|
-
|
30
|
-
def root
|
31
|
-
(
|
32
|
-
(
|
33
|
-
double_quoted_string | single_quoted_string |
|
34
|
-
(Whitespace.absent << any).repeat(1)
|
35
|
-
) << Whitespace.present
|
36
|
-
).aka(:text)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|