node_query 1.0.0 → 1.3.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.md +21 -0
- data/Gemfile.lock +9 -7
- data/README.md +437 -3
- data/lib/node_query/adapter.rb +6 -0
- data/lib/node_query/compiler/attribute.rb +1 -1
- data/lib/node_query/compiler/basic_selector.rb +1 -1
- data/lib/node_query/compiler/comparable.rb +26 -11
- data/lib/node_query/compiler/expression.rb +4 -10
- data/lib/node_query/compiler/expression_list.rb +11 -3
- data/lib/node_query/compiler/identifier.rb +2 -2
- data/lib/node_query/compiler/regexp.rb +7 -10
- data/lib/node_query/compiler/selector.rb +13 -4
- data/lib/node_query/compiler/string.rb +19 -0
- data/lib/node_query/compiler.rb +0 -1
- data/lib/node_query/helper.rb +47 -24
- data/lib/node_query/node_rules.rb +174 -0
- data/lib/node_query/parser_adapter.rb +6 -2
- data/lib/node_query/version.rb +1 -1
- data/lib/node_query.rb +37 -10
- data/lib/node_query_lexer.rex +2 -5
- data/lib/node_query_lexer.rex.rb +287 -0
- data/lib/node_query_parser.racc.rb +302 -0
- data/lib/node_query_parser.y +3 -4
- data/node_query.gemspec +3 -3
- data/sig/node_query/adapter.rbs +11 -0
- data/sig/node_query.rbs +6 -4
- metadata +11 -8
- data/lib/node_query/compiler/evaluated_value.rb +0 -50
@@ -13,12 +13,20 @@ module NodeQuery::Compiler
|
|
13
13
|
|
14
14
|
# Query nodes by the current and the rest expression.
|
15
15
|
# @param node [Node] node to match
|
16
|
+
# @params including_self [boolean] if query the current node.
|
16
17
|
# @return [Array<Node>] matching nodes.
|
17
|
-
def query_nodes(node)
|
18
|
-
matching_nodes = @expression.query_nodes(node)
|
18
|
+
def query_nodes(node, including_self = true)
|
19
|
+
matching_nodes = @expression.query_nodes(node, including_self)
|
19
20
|
return matching_nodes if @rest.nil?
|
20
21
|
|
21
|
-
matching_nodes + @rest.query_nodes(node)
|
22
|
+
matching_nodes + @rest.query_nodes(node, including_self)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check if the node matches the expression list.
|
26
|
+
# @param node [Node] the node
|
27
|
+
# @return [Boolean]
|
28
|
+
def match_node?(node)
|
29
|
+
!query_nodes(node).empty?
|
22
30
|
end
|
23
31
|
|
24
32
|
def to_s
|
@@ -19,8 +19,8 @@ module NodeQuery::Compiler
|
|
19
19
|
# if the node is an Array, return the array of each element's actual value,
|
20
20
|
# otherwise, return the String value.
|
21
21
|
def actual_value(node)
|
22
|
-
if
|
23
|
-
NodeQuery.
|
22
|
+
if NodeQuery.adapter.is_node?(node)
|
23
|
+
NodeQuery.adapter.get_source(node)
|
24
24
|
elsif node.is_a?(::Array)
|
25
25
|
node.map { |n| actual_value(n) }
|
26
26
|
else
|
@@ -13,16 +13,13 @@ module NodeQuery::Compiler
|
|
13
13
|
|
14
14
|
# Check if the regexp value matches the node value.
|
15
15
|
# @param node [Node] the node
|
16
|
-
# @
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@value.match(node.to_s)
|
24
|
-
end
|
25
|
-
operator == '=~' ? match : !match
|
16
|
+
# @return [Boolean] true if the regexp value matches the node value.
|
17
|
+
def is_equal?(node)
|
18
|
+
if NodeQuery.adapter.is_node?(node)
|
19
|
+
@value.match(NodeQuery.adapter.get_source(node))
|
20
|
+
else
|
21
|
+
@value.match(node.to_s)
|
22
|
+
end
|
26
23
|
end
|
27
24
|
|
28
25
|
# Get valid operators.
|
@@ -23,7 +23,7 @@ module NodeQuery::Compiler
|
|
23
23
|
# Check if node matches the selector.
|
24
24
|
# @param node [Parser::AST::Node] the node
|
25
25
|
def match?(node)
|
26
|
-
|
26
|
+
NodeQuery.adapter.is_node?(node) && (!@basic_selector || @basic_selector.match?(node)) && match_pseudo_class?(node)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Query nodes by the selector.
|
@@ -33,8 +33,9 @@ module NodeQuery::Compiler
|
|
33
33
|
# * If relationship is next sibling, it try to match next sibling node.
|
34
34
|
# * If relationship is subsequent sibling, it will match in all sibling nodes.
|
35
35
|
# @param node [Node] node to match
|
36
|
+
# @params including_self [boolean] if query the current node.
|
36
37
|
# @return [Array<Node>] matching nodes.
|
37
|
-
def query_nodes(node)
|
38
|
+
def query_nodes(node, including_self = true)
|
38
39
|
return find_nodes_by_relationship(node) if @relationship
|
39
40
|
|
40
41
|
if node.is_a?(::Array)
|
@@ -44,7 +45,9 @@ module NodeQuery::Compiler
|
|
44
45
|
return find_nodes_by_goto_scope(node) if @goto_scope
|
45
46
|
|
46
47
|
nodes = []
|
47
|
-
|
48
|
+
if including_self && match?(node)
|
49
|
+
nodes << node
|
50
|
+
end
|
48
51
|
if @basic_selector
|
49
52
|
NodeQuery::Helper.handle_recursive_child(node) do |child_node|
|
50
53
|
nodes << child_node if match?(child_node)
|
@@ -86,7 +89,13 @@ module NodeQuery::Compiler
|
|
86
89
|
end
|
87
90
|
else
|
88
91
|
node.children.each do |child_node|
|
89
|
-
|
92
|
+
if NodeQuery.adapter.is_node?(child_node) && :begin == NodeQuery.adapter.get_node_type(child_node)
|
93
|
+
child_node.children.each do |child_child_node|
|
94
|
+
nodes << child_child_node if @rest.match?(child_child_node)
|
95
|
+
end
|
96
|
+
elsif @rest.match?(child_node)
|
97
|
+
nodes << child_node
|
98
|
+
end
|
90
99
|
end
|
91
100
|
end
|
92
101
|
when '+'
|
@@ -5,12 +5,31 @@ module NodeQuery::Compiler
|
|
5
5
|
class String
|
6
6
|
include Comparable
|
7
7
|
|
8
|
+
attr_accessor :base_node
|
9
|
+
|
8
10
|
# Initialize a String.
|
9
11
|
# @param value [String] the string value
|
10
12
|
def initialize(value:)
|
11
13
|
@value = value
|
12
14
|
end
|
13
15
|
|
16
|
+
# Get the expected value.
|
17
|
+
# @example
|
18
|
+
# if the source code of the node is @id = id,
|
19
|
+
# and the @value is "@{{right_vaue}}",
|
20
|
+
# then it returns "@id".
|
21
|
+
# @return [String] the expected string, if it contains evaluated value, evaluate the node value.
|
22
|
+
def expected_value
|
23
|
+
NodeQuery::Helper.evaluate_node_value(base_node, @value)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Check if the actual value equals the node value.
|
27
|
+
# @param node [Node] the node
|
28
|
+
# @return [Boolean] true if the actual value equals the node value.
|
29
|
+
def is_equal?(node)
|
30
|
+
actual_value(node).to_s == expected_value
|
31
|
+
end
|
32
|
+
|
14
33
|
# Get valid operators.
|
15
34
|
# @return [Array] valid operators
|
16
35
|
def valid_operators
|
data/lib/node_query/compiler.rb
CHANGED
@@ -15,7 +15,6 @@ module NodeQuery::Compiler
|
|
15
15
|
|
16
16
|
autoload :ArrayValue, 'node_query/compiler/array_value'
|
17
17
|
autoload :Boolean, 'node_query/compiler/boolean'
|
18
|
-
autoload :EvaluatedValue, 'node_query/compiler/evaluated_value'
|
19
18
|
autoload :Float, 'node_query/compiler/float'
|
20
19
|
autoload :Identifier, 'node_query/compiler/identifier'
|
21
20
|
autoload :Integer, 'node_query/compiler/integer'
|
data/lib/node_query/helper.rb
CHANGED
@@ -1,35 +1,58 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class NodeQuery::Helper
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
class <<self
|
5
|
+
# Get target node by the keys.
|
6
|
+
# @param node [Node] ast node
|
7
|
+
# @param keys [String|Array] keys of child node.
|
8
|
+
# @return [Node|] the target node.
|
9
|
+
def get_target_node(node, keys)
|
10
|
+
return unless node
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
first_key, rest_keys = keys.to_s.split('.', 2)
|
13
|
+
if node.is_a?(Array) && first_key === "*"
|
14
|
+
return node.map { |child_node| get_target_node(child_node, rest_keys) }
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
if node.is_a?(Array) && first_key =~ /\d+/
|
18
|
+
child_node = node[first_key.to_i]
|
19
|
+
elsif node.respond_to?(first_key)
|
20
|
+
child_node = node.send(first_key)
|
21
|
+
elsif first_key == "nodeType"
|
22
|
+
child_node = NodeQuery.adapter.get_node_type(node)
|
23
|
+
end
|
19
24
|
|
20
|
-
|
25
|
+
return child_node unless rest_keys
|
21
26
|
|
22
|
-
|
23
|
-
|
27
|
+
return get_target_node(child_node, rest_keys)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Recursively handle child nodes.
|
31
|
+
# @param node [Node] ast node
|
32
|
+
# @yield [child] Gives a child node.
|
33
|
+
# @yieldparam child [Parser::AST::Node] child node
|
34
|
+
def handle_recursive_child(node, &block)
|
35
|
+
NodeQuery.adapter.get_children(node).each do |child|
|
36
|
+
if NodeQuery.adapter.is_node?(child)
|
37
|
+
block.call(child)
|
38
|
+
handle_recursive_child(child, &block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
24
42
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
43
|
+
# Evaluate node value.
|
44
|
+
# @example
|
45
|
+
# source code of the node is @id = id
|
46
|
+
# evaluated_node_value(node, "@{{right_value}}") # => @id
|
47
|
+
# @param node [Node] ast node
|
48
|
+
# @param str [String] string to be evaluated
|
49
|
+
# @return [String] evaluated string
|
50
|
+
def evaluate_node_value(node, str)
|
51
|
+
str.scan(/{{(.*)}}/).each do |match_data|
|
52
|
+
target_node = NodeQuery::Helper.get_target_node(node, match_data.first)
|
53
|
+
str = str.sub("{{#{match_data.first}}}", NodeQuery.adapter.get_source(target_node))
|
54
|
+
end
|
55
|
+
str
|
33
56
|
end
|
34
57
|
end
|
35
58
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class NodeQuery::NodeRules
|
4
|
+
KEYWORDS = %i[any includes not in not_in gt gte lt lte]
|
5
|
+
|
6
|
+
# Initialize a NodeRules.
|
7
|
+
# @param rules [Hash] the nod rules
|
8
|
+
def initialize(rules)
|
9
|
+
@rules = rules
|
10
|
+
end
|
11
|
+
|
12
|
+
# Query nodes by the rules.
|
13
|
+
# @param node [Node] node to query
|
14
|
+
# @params including_self [boolean] if query the current node.
|
15
|
+
# @return [Array<Node>] matching nodes.
|
16
|
+
def query_nodes(node, including_self = true)
|
17
|
+
matching_nodes = []
|
18
|
+
if (including_self && match_node?(node))
|
19
|
+
matching_nodes.push(node)
|
20
|
+
end
|
21
|
+
NodeQuery::Helper.handle_recursive_child(node) do |child_node|
|
22
|
+
if (match_node?(child_node))
|
23
|
+
matching_nodes.push(child_node)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
matching_nodes
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check if the node matches the rules.
|
30
|
+
# @param node [Node] the node
|
31
|
+
# @return [Boolean]
|
32
|
+
def match_node?(node)
|
33
|
+
flat_hash(@rules).keys.all? do |multi_keys|
|
34
|
+
last_key = multi_keys.last
|
35
|
+
actual = KEYWORDS.include?(last_key) ?
|
36
|
+
NodeQuery::Helper.get_target_node(node, multi_keys[0...-1].join('.')) :
|
37
|
+
NodeQuery::Helper.get_target_node(node, multi_keys.join('.'))
|
38
|
+
expected = expected_value(@rules, multi_keys)
|
39
|
+
expected = NodeQuery::Helper.evaluate_node_value(node, expected) if expected.is_a?(String)
|
40
|
+
case last_key
|
41
|
+
when :any, :includes
|
42
|
+
actual.any? { |actual_value| match_value?(actual_value, expected) }
|
43
|
+
when :not
|
44
|
+
!match_value?(actual, expected)
|
45
|
+
when :in
|
46
|
+
expected.any? { |expected_value| match_value?(actual, expected_value) }
|
47
|
+
when :not_in
|
48
|
+
expected.all? { |expected_value| !match_value?(actual, expected_value) }
|
49
|
+
when :gt
|
50
|
+
actual > expected
|
51
|
+
when :gte
|
52
|
+
actual >= expected
|
53
|
+
when :lt
|
54
|
+
actual < expected
|
55
|
+
when :lte
|
56
|
+
actual <= expected
|
57
|
+
else
|
58
|
+
match_value?(actual, expected)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Compare actual value with expected value.
|
66
|
+
#
|
67
|
+
# @param actual [Object] actual value.
|
68
|
+
# @param expected [Object] expected value.
|
69
|
+
# @return [Boolean]
|
70
|
+
# @raise [Synvert::Core::MethodNotSupported] if expected class is not supported.
|
71
|
+
def match_value?(actual, expected)
|
72
|
+
return true if actual == expected
|
73
|
+
|
74
|
+
case expected
|
75
|
+
when Symbol
|
76
|
+
if actual.is_a?(Parser::AST::Node)
|
77
|
+
actual_source = NodeQuery.adapter.get_source(actual)
|
78
|
+
actual_source == ":#{expected}" || actual_source == expected.to_s
|
79
|
+
else
|
80
|
+
actual.to_sym == expected
|
81
|
+
end
|
82
|
+
when String
|
83
|
+
if actual.is_a?(Parser::AST::Node)
|
84
|
+
actual_source = NodeQuery.adapter.get_source(actual)
|
85
|
+
actual_source == expected || actual_source == unwrap_quote(expected) ||
|
86
|
+
unwrap_quote(actual_source) == expected || unwrap_quote(actual_source) == unwrap_quote(expected)
|
87
|
+
else
|
88
|
+
actual.to_s == expected || wrap_quote(actual.to_s) == expected
|
89
|
+
end
|
90
|
+
when Regexp
|
91
|
+
if actual.is_a?(Parser::AST::Node)
|
92
|
+
actual.to_source =~ Regexp.new(expected.to_s, Regexp::MULTILINE)
|
93
|
+
else
|
94
|
+
actual.to_s =~ Regexp.new(expected.to_s, Regexp::MULTILINE)
|
95
|
+
end
|
96
|
+
when Array
|
97
|
+
return false unless expected.length == actual.length
|
98
|
+
|
99
|
+
actual.zip(expected).all? { |a, e| match_value?(a, e) }
|
100
|
+
when NilClass
|
101
|
+
if actual.is_a?(Parser::AST::Node)
|
102
|
+
:nil == actual.type
|
103
|
+
else
|
104
|
+
actual.nil?
|
105
|
+
end
|
106
|
+
when Numeric
|
107
|
+
if actual.is_a?(Parser::AST::Node)
|
108
|
+
actual.children[0] == expected
|
109
|
+
else
|
110
|
+
actual == expected
|
111
|
+
end
|
112
|
+
when TrueClass
|
113
|
+
:true == actual.type
|
114
|
+
when FalseClass
|
115
|
+
:false == actual.type
|
116
|
+
when Parser::AST::Node
|
117
|
+
actual == expected
|
118
|
+
when Synvert::Core::Rewriter::AnyValue
|
119
|
+
!actual.nil?
|
120
|
+
else
|
121
|
+
raise Synvert::Core::MethodNotSupported, "#{expected.class} is not handled for match_value?"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Convert a hash to flat one.
|
126
|
+
#
|
127
|
+
# @example
|
128
|
+
# flat_hash(type: 'block', caller: {type: 'send', receiver: 'RSpec'})
|
129
|
+
# # {[:type] => 'block', [:caller, :type] => 'send', [:caller, :receiver] => 'RSpec'}
|
130
|
+
# @param h [Hash] original hash.
|
131
|
+
# @return flatten hash.
|
132
|
+
def flat_hash(h, k = [])
|
133
|
+
new_hash = {}
|
134
|
+
h.each_pair do |key, val|
|
135
|
+
if val.is_a?(Hash)
|
136
|
+
new_hash.merge!(flat_hash(val, k + [key]))
|
137
|
+
else
|
138
|
+
new_hash[k + [key]] = val
|
139
|
+
end
|
140
|
+
end
|
141
|
+
new_hash
|
142
|
+
end
|
143
|
+
|
144
|
+
# Get expected value from rules.
|
145
|
+
#
|
146
|
+
# @param rules [Hash]
|
147
|
+
# @param multi_keys [Array<Symbol>]
|
148
|
+
# @return [Object] expected value.
|
149
|
+
def expected_value(rules, multi_keys)
|
150
|
+
multi_keys.inject(rules) { |o, key| o[key] }
|
151
|
+
end
|
152
|
+
|
153
|
+
# Wrap the string with single or double quote.
|
154
|
+
# @param string [String]
|
155
|
+
# @return [String]
|
156
|
+
def wrap_quote(string)
|
157
|
+
if string.include?("'")
|
158
|
+
"\"#{string}\""
|
159
|
+
else
|
160
|
+
"'#{string}'"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Unwrap the quote from the string.
|
165
|
+
# @param string [String]
|
166
|
+
# @return [String]
|
167
|
+
def unwrap_quote(string)
|
168
|
+
if (string[0] == '"' && string[-1] == '"') || (string[0] == "'" && string[-1] == "'")
|
169
|
+
string[1...-1]
|
170
|
+
else
|
171
|
+
string
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class NodeQuery::ParserAdapter
|
4
|
+
def is_node?(node)
|
5
|
+
node.is_a?(Parser::AST::Node)
|
6
|
+
end
|
7
|
+
|
4
8
|
def get_node_type(node)
|
5
9
|
node.type
|
6
10
|
end
|
@@ -10,11 +14,11 @@ class NodeQuery::ParserAdapter
|
|
10
14
|
end
|
11
15
|
|
12
16
|
def get_children(node)
|
13
|
-
node.
|
17
|
+
node.children
|
14
18
|
end
|
15
19
|
|
16
20
|
def get_siblings(node)
|
17
21
|
index = node.parent.children.index(node)
|
18
22
|
node.parent.children[index + 1..]
|
19
23
|
end
|
20
|
-
end
|
24
|
+
end
|
data/lib/node_query/version.rb
CHANGED
data/lib/node_query.rb
CHANGED
@@ -3,13 +3,16 @@
|
|
3
3
|
require 'active_support/core_ext/array'
|
4
4
|
|
5
5
|
require_relative "node_query/version"
|
6
|
-
require_relative "node_query/parser_adapter"
|
7
|
-
require_relative "node_query/compiler"
|
8
|
-
require_relative "node_query/helper"
|
9
6
|
require_relative "./node_query_lexer.rex"
|
10
7
|
require_relative "./node_query_parser.racc"
|
11
8
|
|
12
9
|
class NodeQuery
|
10
|
+
autoload :Adapter, "node_query/adapter"
|
11
|
+
autoload :ParserAdapter, "node_query/parser_adapter"
|
12
|
+
autoload :Compiler, "node_query/compiler"
|
13
|
+
autoload :Helper, "node_query/helper"
|
14
|
+
autoload :NodeRules, "node_query/node_rules"
|
15
|
+
|
13
16
|
# Configure NodeQuery
|
14
17
|
# @param [Hash] options options to configure
|
15
18
|
# @option options [NodeQuery::Adapter] :adapter the adpater
|
@@ -19,20 +22,44 @@ class NodeQuery
|
|
19
22
|
|
20
23
|
# Get the adapter
|
21
24
|
# @return [NodeQuery::Adapter] current adapter, by default is {NodeQuery::ParserAdapter}
|
22
|
-
def self.
|
25
|
+
def self.adapter
|
23
26
|
@adapter ||= ParserAdapter.new
|
24
27
|
end
|
25
28
|
|
26
29
|
# Initialize a NodeQuery.
|
27
|
-
# @param
|
28
|
-
def initialize(
|
29
|
-
|
30
|
+
# @param nqlOrRules [String | Hash] node query language or node rules
|
31
|
+
def initialize(nqlOrRules)
|
32
|
+
if nqlOrRules.is_a?(String)
|
33
|
+
@expression = NodeQueryParser.new.parse(nqlOrRules)
|
34
|
+
else
|
35
|
+
@rules = NodeRules.new(nqlOrRules)
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
32
|
-
#
|
39
|
+
# Query matching nodes.
|
33
40
|
# @param node [Node] ast node
|
41
|
+
# @param including_self [boolean] if check the node itself
|
34
42
|
# @return [Array<Node>] matching child nodes
|
35
|
-
def
|
36
|
-
@expression
|
43
|
+
def query_nodes(node, including_self = true)
|
44
|
+
if @expression
|
45
|
+
@expression.query_nodes(node, including_self)
|
46
|
+
elsif @rules
|
47
|
+
@rules.query_nodes(node, including_self)
|
48
|
+
else
|
49
|
+
[]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Check if the node matches the nql or rules.
|
54
|
+
# @param node [Node] the node
|
55
|
+
# @return [Boolean]
|
56
|
+
def match_node?(node)
|
57
|
+
if @expression
|
58
|
+
@expression.match_node?(node)
|
59
|
+
elsif @rules
|
60
|
+
@rules.match_node?(node)
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
37
64
|
end
|
38
65
|
end
|
data/lib/node_query_lexer.rex
CHANGED
@@ -7,11 +7,9 @@ macros
|
|
7
7
|
CLOSE_ARRAY /\)/
|
8
8
|
OPEN_SELECTOR /\(/
|
9
9
|
CLOSE_SELECTOR /\)/
|
10
|
-
OPEN_DYNAMIC_ATTRIBUTE /{{/
|
11
|
-
CLOSE_DYNAMIC_ATTRIBUTE /}}/
|
12
10
|
NODE_TYPE /\.[a-z]+/
|
13
|
-
IDENTIFIER /[
|
14
|
-
IDENTIFIER_VALUE /[
|
11
|
+
IDENTIFIER /[@\*\.\w]*\w/
|
12
|
+
IDENTIFIER_VALUE /[@\.\w!&:\?<>=]+/
|
15
13
|
FALSE /false/
|
16
14
|
FLOAT /\d+\.\d+/
|
17
15
|
INTEGER /\d+/
|
@@ -59,7 +57,6 @@ rules
|
|
59
57
|
:VALUE /\[\]/ { [:tIDENTIFIER_VALUE, text] }
|
60
58
|
:VALUE /:\[\]=/ { [:tSYMBOL, text[1..-1].to_sym] }
|
61
59
|
:VALUE /:\[\]/ { [:tSYMBOL, text[1..-1].to_sym] }
|
62
|
-
:VALUE /{{#{IDENTIFIER}}}/ { [:tDYNAMIC_ATTRIBUTE, text[2..-3]] }
|
63
60
|
:VALUE /#{OPEN_ARRAY}/ { @state = :ARRAY_VALUE; [:tOPEN_ARRAY, text] }
|
64
61
|
:VALUE /#{CLOSE_ATTRIBUTE}/ { @nested_count -= 1; @state = @nested_count == 0 ? nil : :VALUE; [:tCLOSE_ATTRIBUTE, text] }
|
65
62
|
:VALUE /#{NIL}\?/ { [:tIDENTIFIER_VALUE, text] }
|