synvert-core 1.3.1 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51aff3b9c1c43ab2e6b3c093b65a42cb97536b900cf0aa8d0081e7e8716346f0
4
- data.tar.gz: 6902ad17b6fa2d1ab2a5d5294f3bb1f29903a12c7ad8dd15cc7dae56173a440a
3
+ metadata.gz: 741ca9c2f6f29e5bbafbc5b63d94b3cd9a56aa20e8a00f3f70830b73b1fb697e
4
+ data.tar.gz: a8bbf6e0c48a4af42578abb20807f3d86359fc069dc85ff90e12cf011f076998
5
5
  SHA512:
6
- metadata.gz: 74cc5bb2cf144fba8bbd8ad647971efeba9473138d1cc5b416b45aa940c22f8929cefdd32b5e692c0dc1a9c9786d49dd8b441f1949a58256cec015a9697f2a43
7
- data.tar.gz: c08abee0bf9fd0cba7cd5248f9020c4c30dadc25c06c5b358a122ccb09e7171878eae85cd498a0fb788aa2987fcf0302916c49cca0f9eaabc77b55e3a43d6a3a
6
+ metadata.gz: 7fcadf632c863b1f3ba410b65f63c741b594255567f337ebc86c51ae45e681484653b45eec01fc5c3e3a4ea170a6bd38e899bdf22f65b2e980d58cac8c11cfcd
7
+ data.tar.gz: 80ebe8f07ef9679c6921233d52b46979a6bfb895e4b63b974672dec193ef52ce08c40454d2a92fd509f12b8f3567065bb7d2dbee33af7bca37a96246e6373381
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.4.0 (2022-05-21)
4
+
5
+ * Drop support `:first-child` and `:last-child`
6
+ * Redefine goto scope in nql
7
+ * Fix shift/reduce conflict
8
+
3
9
  ## 1.3.1 (2022-05-14)
4
10
 
5
11
  * Add `add_comma` option to remove extra comma
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core::NodeQuery::Compiler
4
- # SimpleSelector used to match nodes, it combines by node type and/or attribute list.
5
- class SimpleSelector
6
- # Initialize a SimpleSelector.
4
+ # BasicSelector used to match nodes, it combines by node type and/or attribute list.
5
+ class BasicSelector
6
+ # Initialize a BasicSelector.
7
7
  # @param node_type [String] the node type
8
8
  # @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
9
9
  def initialize(node_type:, attribute_list: nil)
@@ -20,8 +20,7 @@ module Synvert::Core::NodeQuery::Compiler
20
20
  end
21
21
 
22
22
  def to_s
23
- result = []
24
- result << ".#{@node_type}" if @node_type
23
+ result = [".#{@node_type}"]
25
24
  result << @attribute_list.to_s if @attribute_list
26
25
  result.join('')
27
26
  end
@@ -21,13 +21,14 @@ module Synvert::Core::NodeQuery::Compiler
21
21
  # Query nodes by the selector and the rest expression.
22
22
  #
23
23
  # @param node [Parser::AST::Node] node to match
24
- # @param descendant_match [Boolean] whether to match in descendant node
25
24
  # @return [Array<Parser::AST::Node>] matching nodes.
26
- def query_nodes(node, descendant_match = true)
27
- matching_nodes = find_nodes_by_selector(node, descendant_match)
25
+ def query_nodes(node)
26
+ matching_nodes = @selector.query_nodes(node)
28
27
  return matching_nodes if @rest.nil?
29
28
 
30
- matching_nodes.flat_map { |matching_node| find_nodes_by_rest(matching_node, descendant_match) }
29
+ matching_nodes.flat_map do |matching_node|
30
+ @rest.query_nodes(matching_node)
31
+ end
31
32
  end
32
33
 
33
34
  def to_s
@@ -36,23 +37,5 @@ module Synvert::Core::NodeQuery::Compiler
36
37
  result << @rest.to_s if @rest
37
38
  result.join(' ')
38
39
  end
39
-
40
- private
41
-
42
- # Find nodes by @rest
43
- # @param node [Parser::AST::Node] node to match
44
- # @param descendant_match [Boolean] whether to match in descendant node
45
- def find_nodes_by_rest(node, descendant_match = false)
46
- @rest.query_nodes(node, descendant_match)
47
- end
48
-
49
- # Find nodes with nil relationship.
50
- # @param node [Parser::AST::Node] node to match
51
- # @param descendant_match [Boolean] whether to match in descendant node
52
- def find_nodes_by_selector(node, descendant_match = true)
53
- return Array(node) if !@selector
54
-
55
- @selector.query_nodes(node, descendant_match)
56
- end
57
40
  end
58
41
  end
@@ -7,17 +7,15 @@ module Synvert::Core::NodeQuery::Compiler
7
7
  # @param goto_scope [String] goto scope
8
8
  # @param relationship [Symbol] the relationship between the selectors, it can be descendant <code>nil</code>, child <code>></code>, next sibling <code>+</code> or subsequent sibing <code>~</code>.
9
9
  # @param rest [Synvert::Core::NodeQuery::Compiler::Selector] the rest selector
10
- # @param simple_selector [Synvert::Core::NodeQuery::Compiler::SimpleSelector] the simple selector
10
+ # @param basic_selector [Synvert::Core::NodeQuery::Compiler::BasicSelector] the simple selector
11
11
  # @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
12
- # @param index [Integer] the index
13
12
  # @param pseudo_class [String] the pseudo class, can be <code>has</code> or <code>not_has</code>
14
13
  # @param pseudo_selector [Synvert::Core::NodeQuery::Compiler::Expression] the pseudo selector
15
- def initialize(goto_scope: nil, relationship: nil, rest: nil, simple_selector: nil, index: nil, pseudo_class: nil, pseudo_selector: nil)
14
+ def initialize(goto_scope: nil, relationship: nil, rest: nil, basic_selector: nil, pseudo_class: nil, pseudo_selector: nil)
16
15
  @goto_scope = goto_scope
17
16
  @relationship = relationship
18
17
  @rest = rest
19
- @simple_selector = simple_selector
20
- @index = index
18
+ @basic_selector = basic_selector
21
19
  @pseudo_class = pseudo_class
22
20
  @pseudo_selector = pseudo_selector
23
21
  end
@@ -25,9 +23,7 @@ module Synvert::Core::NodeQuery::Compiler
25
23
  # Check if node matches the selector.
26
24
  # @param node [Parser::AST::Node] the node
27
25
  def match?(node)
28
- node.is_a?(::Parser::AST::Node) &&
29
- (!@simple_selector || @simple_selector.match?(node)) &&
30
- match_pseudo_class?(node)
26
+ node.is_a?(::Parser::AST::Node) && (!@basic_selector || @basic_selector.match?(node)) && match_pseudo_class?(node)
31
27
  end
32
28
 
33
29
  # Query nodes by the selector.
@@ -38,47 +34,33 @@ module Synvert::Core::NodeQuery::Compiler
38
34
  # * If relationship is next sibling, it try to match next sibling node.
39
35
  # * If relationship is subsequent sibling, it will match in all sibling nodes.
40
36
  # @param node [Parser::AST::Node] node to match
41
- # @param descendant_match [Boolean] whether to match in descendant node
42
37
  # @return [Array<Parser::AST::Node>] matching nodes.
43
- def query_nodes(node, descendant_match = true)
38
+ def query_nodes(node)
44
39
  return find_nodes_by_relationship(node) if @relationship
45
40
 
46
41
  if node.is_a?(::Array)
47
- return node.flat_map { |child_node| query_nodes(child_node, descendant_match) }
42
+ return node.flat_map { |child_node| query_nodes(child_node) }
48
43
  end
49
44
 
50
45
  return find_nodes_by_goto_scope(node) if @goto_scope
51
46
 
52
47
  nodes = []
53
48
  nodes << node if match?(node)
54
- if descendant_match && @simple_selector
49
+ if @basic_selector
55
50
  node.recursive_children do |child_node|
56
51
  nodes << child_node if match?(child_node)
57
52
  end
58
53
  end
59
- filter(nodes)
54
+ nodes
60
55
  end
61
56
 
62
57
  def to_s
63
58
  result = []
64
- result << "<#{@goto_scope}> " if @goto_scope
59
+ result << "#{@goto_scope} " if @goto_scope
65
60
  result << "#{@relationship} " if @relationship
66
61
  result << @rest.to_s if @rest
67
- result << @simple_selector.to_s if @simple_selector
62
+ result << @basic_selector.to_s if @basic_selector
68
63
  result << ":#{@pseudo_class}(#{@pseudo_selector})" if @pseudo_class
69
- if @index
70
- result <<
71
- case @index
72
- when 0
73
- ':first-child'
74
- when -1
75
- ':last-child'
76
- when (1..)
77
- ":nth-child(#{@index + 1})"
78
- else # ...-1
79
- ":nth-last-child(#{-@index})"
80
- end
81
- end
82
64
  result.join('')
83
65
  end
84
66
 
@@ -88,7 +70,7 @@ module Synvert::Core::NodeQuery::Compiler
88
70
  # @param node [Parser::AST::Node] node to match
89
71
  def find_nodes_by_goto_scope(node)
90
72
  @goto_scope.split('.').each { |scope| node = node.send(scope) }
91
- @rest.query_nodes(node, false)
73
+ @rest.query_nodes(node)
92
74
  end
93
75
 
94
76
  # Find ndoes by @relationship
@@ -114,7 +96,7 @@ module Synvert::Core::NodeQuery::Compiler
114
96
  nodes << sibling_node if @rest.match?(sibling_node)
115
97
  end
116
98
  end
117
- return filter(nodes)
99
+ nodes
118
100
  end
119
101
 
120
102
  def match_pseudo_class?(node)
@@ -127,12 +109,5 @@ module Synvert::Core::NodeQuery::Compiler
127
109
  true
128
110
  end
129
111
  end
130
-
131
- # Filter nodes by index.
132
- def filter(nodes)
133
- return nodes if @index.nil?
134
-
135
- nodes[@index] ? [nodes[@index]] : []
136
- end
137
112
  end
138
113
  end
@@ -8,7 +8,7 @@ module Synvert::Core::NodeQuery::Compiler
8
8
 
9
9
  autoload :Expression, 'synvert/core/node_query/compiler/expression'
10
10
  autoload :Selector, 'synvert/core/node_query/compiler/selector'
11
- autoload :SimpleSelector, 'synvert/core/node_query/compiler/simple_selector'
11
+ autoload :BasicSelector, 'synvert/core/node_query/compiler/basic_selector'
12
12
  autoload :AttributeList, 'synvert/core/node_query/compiler/attribute_list'
13
13
  autoload :Attribute, 'synvert/core/node_query/compiler/attribute'
14
14
 
@@ -7,8 +7,6 @@ macros
7
7
  CLOSE_ARRAY /\)/
8
8
  OPEN_SELECTOR /\(/
9
9
  CLOSE_SELECTOR /\)/
10
- OPEN_GOTO_SCOPE /</
11
- CLOSE_GOTO_SCOPE />/
12
10
  OPEN_DYNAMIC_ATTRIBUTE /{{/
13
11
  CLOSE_DYNAMIC_ATTRIBUTE /}}/
14
12
  NODE_TYPE /\.[a-z]+/
@@ -29,23 +27,16 @@ rules
29
27
 
30
28
  # [:state] pattern [actions]
31
29
  /\s+/
32
- /:first-child/ { [:tINDEX, 0] }
33
- /:last-child/ { [:tINDEX, -1] }
34
- /:nth-child\(\d+\)/ { [:tINDEX, text.sub(':nth-child(', '').to_i - 1] }
35
- /:nth-last-child\(\d+\)/ { [:tINDEX, -text.sub(':nth-last-child(', '').to_i] }
36
30
  /:has/ { [:tPSEUDO_CLASS, text[1..-1]] }
37
31
  /:not_has/ { [:tPSEUDO_CLASS, text[1..-1]] }
38
32
  /#{NODE_TYPE}/ { [:tNODE_TYPE, text[1..]] }
33
+ /#{IDENTIFIER}/ { [:tGOTO_SCOPE, text] }
39
34
  />/ { [:tRELATIONSHIP, text] }
40
35
  /~/ { [:tRELATIONSHIP, text] }
41
36
  /\+/ { [:tRELATIONSHIP, text] }
42
37
  /#{OPEN_SELECTOR}/ { [:tOPEN_SELECTOR, text] }
43
38
  /#{CLOSE_SELECTOR}/ { [:tCLOSE_SELECTOR, text] }
44
- /#{OPEN_GOTO_SCOPE}/ { @state = :GOTO_SCOPE; [:tOPEN_GOTO_SCOPE, text] }
45
39
  /#{OPEN_ATTRIBUTE}/ { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
46
- :GOTO_SCOPE /\s+/
47
- :GOTO_SCOPE /#{IDENTIFIER}/ { [:tIDENTIFIER, text] }
48
- :GOTO_SCOPE /#{CLOSE_GOTO_SCOPE}/ { @state = nil; [:tCLOSE_GOTO_SCOPE, text] }
49
40
  :KEY /\s+/
50
41
  :KEY /\^=/ { @state = :VALUE; [:tOPERATOR, '^='] }
51
42
  :KEY /\$=/ { @state = :VALUE; [:tOPERATOR, '$='] }
@@ -1,4 +1,3 @@
1
- # typed: false
2
1
  # frozen_string_literal: true
3
2
  # encoding: UTF-8
4
3
  #--
@@ -21,8 +20,6 @@ class Synvert::Core::NodeQuery::Lexer
21
20
  CLOSE_ARRAY = /\)/
22
21
  OPEN_SELECTOR = /\(/
23
22
  CLOSE_SELECTOR = /\)/
24
- OPEN_GOTO_SCOPE = /</
25
- CLOSE_GOTO_SCOPE = />/
26
23
  OPEN_DYNAMIC_ATTRIBUTE = /{{/
27
24
  CLOSE_DYNAMIC_ATTRIBUTE = /}}/
28
25
  NODE_TYPE = /\.[a-z]+/
@@ -128,20 +125,14 @@ class Synvert::Core::NodeQuery::Lexer
128
125
  case
129
126
  when ss.skip(/\s+/) then
130
127
  # do nothing
131
- when ss.skip(/:first-child/) then
132
- action { [:tINDEX, 0] }
133
- when ss.skip(/:last-child/) then
134
- action { [:tINDEX, -1] }
135
- when text = ss.scan(/:nth-child\(\d+\)/) then
136
- action { [:tINDEX, text.sub(':nth-child(', '').to_i - 1] }
137
- when text = ss.scan(/:nth-last-child\(\d+\)/) then
138
- action { [:tINDEX, -text.sub(':nth-last-child(', '').to_i] }
139
128
  when text = ss.scan(/:has/) then
140
129
  action { [:tPSEUDO_CLASS, text[1..-1]] }
141
130
  when text = ss.scan(/:not_has/) then
142
131
  action { [:tPSEUDO_CLASS, text[1..-1]] }
143
132
  when text = ss.scan(/#{NODE_TYPE}/) then
144
133
  action { [:tNODE_TYPE, text[1..]] }
134
+ when text = ss.scan(/#{IDENTIFIER}/) then
135
+ action { [:tGOTO_SCOPE, text] }
145
136
  when text = ss.scan(/>/) then
146
137
  action { [:tRELATIONSHIP, text] }
147
138
  when text = ss.scan(/~/) then
@@ -152,26 +143,12 @@ class Synvert::Core::NodeQuery::Lexer
152
143
  action { [:tOPEN_SELECTOR, text] }
153
144
  when text = ss.scan(/#{CLOSE_SELECTOR}/) then
154
145
  action { [:tCLOSE_SELECTOR, text] }
155
- when text = ss.scan(/#{OPEN_GOTO_SCOPE}/) then
156
- action { @state = :GOTO_SCOPE; [:tOPEN_GOTO_SCOPE, text] }
157
146
  when text = ss.scan(/#{OPEN_ATTRIBUTE}/) then
158
147
  action { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
159
148
  else
160
149
  text = ss.string[ss.pos .. -1]
161
150
  raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
162
151
  end
163
- when :GOTO_SCOPE then
164
- case
165
- when ss.skip(/\s+/) then
166
- # do nothing
167
- when text = ss.scan(/#{IDENTIFIER}/) then
168
- action { [:tIDENTIFIER, text] }
169
- when text = ss.scan(/#{CLOSE_GOTO_SCOPE}/) then
170
- action { @state = nil; [:tCLOSE_GOTO_SCOPE, text] }
171
- else
172
- text = ss.string[ss.pos .. -1]
173
- raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
174
- end
175
152
  when :KEY then
176
153
  case
177
154
  when ss.skip(/\s+/) then
@@ -1,4 +1,3 @@
1
- # typed: true
2
1
  #
3
2
  # DO NOT MODIFY!!!!
4
3
  # This file is automatically generated by Racc 1.6.0
@@ -26,98 +25,94 @@ module Synvert
26
25
  ##### State transition tables begin ###
27
26
 
28
27
  racc_action_table = [
29
- 7, 8, 7, 12, 41, 10, 11, 7, 4, 5,
30
- 33, 41, 31, 14, 16, 17, 18, 33, 6, 20,
31
- 42, 34, 35, 36, 37, 38, 39, 40, 34, 35,
32
- 36, 37, 38, 39, 40, 7, 7, 22, 24, 41,
33
- 26, 27, 4, 5, 28, 33, 16, 7, 45, 46,
34
- 48, nil, 6, 4, 5, nil, 34, 35, 36, 37,
35
- 38, 39, 40, 6, 7, nil, 7, nil, 7, nil,
36
- 4, 5, 4, 5, 4, 5, nil, nil, nil, nil,
37
- 6, nil, 6, nil, 6 ]
28
+ 7, 7, 6, 8, 10, 34, 14, 4, 5, 15,
29
+ 26, 18, 24, 19, 20, 21, 14, 38, 39, 27,
30
+ 28, 29, 30, 31, 32, 33, 7, 41, 7, 6,
31
+ nil, 34, nil, 7, 4, 5, 26, nil, 34, 35,
32
+ nil, nil, nil, 26, nil, 27, 28, 29, 30, 31,
33
+ 32, 33, 27, 28, 29, 30, 31, 32, 33, 7,
34
+ 6, 7, 6, 7, 6, 4, 5, 4, 5, 4,
35
+ 5 ]
38
36
 
39
37
  racc_action_check = [
40
- 27, 1, 0, 4, 27, 3, 3, 31, 0, 0,
41
- 27, 31, 27, 6, 7, 8, 11, 31, 0, 14,
42
- 31, 27, 27, 27, 27, 27, 27, 27, 31, 31,
43
- 31, 31, 31, 31, 31, 44, 2, 16, 19, 44,
44
- 21, 22, 2, 2, 23, 44, 26, 5, 33, 43,
45
- 45, nil, 2, 5, 5, nil, 44, 44, 44, 44,
46
- 44, 44, 44, 5, 12, nil, 18, nil, 20, nil,
47
- 12, 12, 18, 18, 20, 20, nil, nil, nil, nil,
48
- 12, nil, 18, nil, 20 ]
38
+ 21, 0, 0, 1, 4, 21, 7, 0, 0, 8,
39
+ 21, 14, 21, 16, 17, 18, 20, 26, 36, 21,
40
+ 21, 21, 21, 21, 21, 21, 24, 38, 2, 2,
41
+ nil, 24, nil, 37, 2, 2, 24, nil, 37, 24,
42
+ nil, nil, nil, 37, nil, 24, 24, 24, 24, 24,
43
+ 24, 24, 37, 37, 37, 37, 37, 37, 37, 5,
44
+ 5, 6, 6, 10, 10, 5, 5, 6, 6, 10,
45
+ 10 ]
49
46
 
50
47
  racc_action_pointer = [
51
- 0, 1, 34, -2, -13, 45, 8, 4, 15, nil,
52
- nil, 0, 62, nil, 0, nil, 33, nil, 64, 21,
53
- 66, 29, 21, 27, nil, nil, 36, -2, nil, nil,
54
- nil, 5, nil, 26, nil, nil, nil, nil, nil, nil,
55
- nil, nil, nil, 34, 33, 37, nil, nil, nil ]
48
+ -1, 3, 26, nil, -12, 57, 59, -4, 9, nil,
49
+ 61, nil, nil, nil, 6, nil, -4, 3, -3, nil,
50
+ 6, -2, nil, nil, 24, nil, -3, nil, nil, nil,
51
+ nil, nil, nil, nil, nil, nil, 3, 31, 14, nil,
52
+ nil, nil ]
56
53
 
57
54
  racc_action_default = [
58
- -28, -28, -2, -3, -28, -28, -28, -9, -28, -1,
59
- -4, -28, -28, -7, -28, -10, -28, 49, -28, -28,
60
- -28, -28, -28, -28, -6, -8, -12, -28, -5, -11,
61
- -13, -28, -18, -28, -20, -21, -22, -23, -24, -25,
62
- -26, -27, -14, -28, -17, -28, -15, -16, -19 ]
55
+ -26, -26, -2, -3, -26, -26, -26, -7, -26, -1,
56
+ -26, -5, -6, -8, -26, 42, -26, -26, -26, -4,
57
+ -10, -26, -9, -11, -26, -16, -26, -18, -19, -20,
58
+ -21, -22, -23, -24, -25, -12, -26, -15, -26, -13,
59
+ -14, -17 ]
63
60
 
64
61
  racc_goto_table = [
65
- 15, 32, 13, 43, 1, 32, 9, 21, 30, 19,
66
- nil, nil, nil, nil, nil, 23, 47, 25, 32, 29 ]
62
+ 25, 13, 36, 25, 11, 12, 1, 17, 9, 16,
63
+ 23, nil, nil, nil, 22, 40, 25 ]
67
64
 
68
65
  racc_goto_check = [
69
- 4, 3, 2, 7, 1, 3, 1, 5, 6, 2,
70
- nil, nil, nil, nil, nil, 2, 7, 2, 3, 4 ]
66
+ 3, 4, 7, 3, 2, 2, 1, 5, 1, 2,
67
+ 6, nil, nil, nil, 4, 7, 3 ]
71
68
 
72
69
  racc_goto_pointer = [
73
- nil, 4, -3, -26, -7, -9, -19, -28 ]
70
+ nil, 6, -1, -21, -6, -7, -11, -22 ]
74
71
 
75
72
  racc_goto_default = [
76
- nil, nil, 2, 3, nil, nil, 44, nil ]
73
+ nil, nil, 2, 3, nil, nil, 37, nil ]
77
74
 
78
75
  racc_reduce_table = [
79
76
  0, 0, :racc_error,
80
- 2, 31, :_reduce_1,
81
- 1, 31, :_reduce_2,
82
- 1, 32, :_reduce_3,
83
- 2, 32, :_reduce_4,
84
- 5, 32, :_reduce_5,
85
- 4, 32, :_reduce_6,
86
- 2, 32, :_reduce_7,
87
- 4, 32, :_reduce_8,
88
- 1, 33, :_reduce_9,
89
- 2, 33, :_reduce_10,
90
- 4, 34, :_reduce_11,
91
- 3, 34, :_reduce_12,
92
- 3, 35, :_reduce_13,
93
- 4, 35, :_reduce_14,
94
- 5, 35, :_reduce_15,
95
- 2, 37, :_reduce_16,
96
- 1, 37, :_reduce_17,
97
- 1, 36, :_reduce_none,
98
- 3, 36, :_reduce_19,
99
- 1, 36, :_reduce_20,
100
- 1, 36, :_reduce_21,
101
- 1, 36, :_reduce_22,
102
- 1, 36, :_reduce_23,
103
- 1, 36, :_reduce_24,
104
- 1, 36, :_reduce_25,
105
- 1, 36, :_reduce_26,
106
- 1, 36, :_reduce_27 ]
107
-
108
- racc_reduce_n = 28
109
-
110
- racc_shift_n = 49
77
+ 2, 29, :_reduce_1,
78
+ 1, 29, :_reduce_2,
79
+ 1, 30, :_reduce_3,
80
+ 4, 30, :_reduce_4,
81
+ 2, 30, :_reduce_5,
82
+ 2, 30, :_reduce_6,
83
+ 1, 31, :_reduce_7,
84
+ 2, 31, :_reduce_8,
85
+ 4, 32, :_reduce_9,
86
+ 3, 32, :_reduce_10,
87
+ 3, 33, :_reduce_11,
88
+ 4, 33, :_reduce_12,
89
+ 5, 33, :_reduce_13,
90
+ 2, 35, :_reduce_14,
91
+ 1, 35, :_reduce_15,
92
+ 1, 34, :_reduce_none,
93
+ 3, 34, :_reduce_17,
94
+ 1, 34, :_reduce_18,
95
+ 1, 34, :_reduce_19,
96
+ 1, 34, :_reduce_20,
97
+ 1, 34, :_reduce_21,
98
+ 1, 34, :_reduce_22,
99
+ 1, 34, :_reduce_23,
100
+ 1, 34, :_reduce_24,
101
+ 1, 34, :_reduce_25 ]
102
+
103
+ racc_reduce_n = 26
104
+
105
+ racc_shift_n = 42
111
106
 
112
107
  racc_token_table = {
113
108
  false => 0,
114
109
  :error => 1,
115
110
  :tNODE_TYPE => 2,
116
- :tATTRIBUTE => 3,
117
- :tKEY => 4,
118
- :tIDENTIFIER => 5,
119
- :tIDENTIFIER_VALUE => 6,
120
- :tINDEX => 7,
111
+ :tGOTO_SCOPE => 3,
112
+ :tATTRIBUTE => 4,
113
+ :tKEY => 5,
114
+ :tIDENTIFIER => 6,
115
+ :tIDENTIFIER_VALUE => 7,
121
116
  :tPSEUDO_CLASS => 8,
122
117
  :tRELATIONSHIP => 9,
123
118
  :tOPEN_ATTRIBUTE => 10,
@@ -128,20 +123,18 @@ racc_token_table = {
128
123
  :tCLOSE_ARRAY => 15,
129
124
  :tOPEN_SELECTOR => 16,
130
125
  :tCLOSE_SELECTOR => 17,
131
- :tOPEN_GOTO_SCOPE => 18,
132
- :tCLOSE_GOTO_SCOPE => 19,
133
- :tOPERATOR => 20,
134
- :tARRAY_VALUE => 21,
135
- :tDYNAMIC_ATTRIBUTE => 22,
136
- :tBOOLEAN => 23,
137
- :tFLOAT => 24,
138
- :tINTEGER => 25,
139
- :tNIL => 26,
140
- :tREGEXP => 27,
141
- :tSTRING => 28,
142
- :tSYMBOL => 29 }
143
-
144
- racc_nt_base = 30
126
+ :tOPERATOR => 18,
127
+ :tARRAY_VALUE => 19,
128
+ :tDYNAMIC_ATTRIBUTE => 20,
129
+ :tBOOLEAN => 21,
130
+ :tFLOAT => 22,
131
+ :tINTEGER => 23,
132
+ :tNIL => 24,
133
+ :tREGEXP => 25,
134
+ :tSTRING => 26,
135
+ :tSYMBOL => 27 }
136
+
137
+ racc_nt_base = 28
145
138
 
146
139
  racc_use_result_var = false
147
140
 
@@ -165,11 +158,11 @@ Racc_token_to_s_table = [
165
158
  "$end",
166
159
  "error",
167
160
  "tNODE_TYPE",
161
+ "tGOTO_SCOPE",
168
162
  "tATTRIBUTE",
169
163
  "tKEY",
170
164
  "tIDENTIFIER",
171
165
  "tIDENTIFIER_VALUE",
172
- "tINDEX",
173
166
  "tPSEUDO_CLASS",
174
167
  "tRELATIONSHIP",
175
168
  "tOPEN_ATTRIBUTE",
@@ -180,8 +173,6 @@ Racc_token_to_s_table = [
180
173
  "tCLOSE_ARRAY",
181
174
  "tOPEN_SELECTOR",
182
175
  "tCLOSE_SELECTOR",
183
- "tOPEN_GOTO_SCOPE",
184
- "tCLOSE_GOTO_SCOPE",
185
176
  "tOPERATOR",
186
177
  "tARRAY_VALUE",
187
178
  "tDYNAMIC_ATTRIBUTE",
@@ -195,7 +186,7 @@ Racc_token_to_s_table = [
195
186
  "$start",
196
187
  "expression",
197
188
  "selector",
198
- "simple_selector",
189
+ "basic_selector",
199
190
  "attribute_list",
200
191
  "attribute",
201
192
  "value",
@@ -216,100 +207,92 @@ def _reduce_2(val, _values)
216
207
  end
217
208
 
218
209
  def _reduce_3(val, _values)
219
- Compiler::Selector.new(simple_selector: val[0])
210
+ Compiler::Selector.new(basic_selector: val[0])
220
211
  end
221
212
 
222
213
  def _reduce_4(val, _values)
223
- Compiler::Selector.new(simple_selector: val[0], index: val[1])
214
+ Compiler::Selector.new(pseudo_class: val[0], pseudo_selector: val[2])
224
215
  end
225
216
 
226
217
  def _reduce_5(val, _values)
227
- Compiler::Selector.new(simple_selector: val[0], pseudo_class: val[1], pseudo_selector: val[3])
218
+ Compiler::Selector.new(relationship: val[0], rest: val[1])
228
219
  end
229
220
 
230
221
  def _reduce_6(val, _values)
231
- Compiler::Selector.new(pseudo_class: val[0], pseudo_selector: val[2])
222
+ Compiler::Selector.new(goto_scope: val[0], rest: val[1])
232
223
  end
233
224
 
234
225
  def _reduce_7(val, _values)
235
- Compiler::Selector.new(relationship: val[0], rest: val[1])
226
+ Compiler::BasicSelector.new(node_type: val[0])
236
227
  end
237
228
 
238
229
  def _reduce_8(val, _values)
239
- Compiler::Selector.new(goto_scope: val[1], rest: val[3])
230
+ Compiler::BasicSelector.new(node_type: val[0], attribute_list: val[1])
240
231
  end
241
232
 
242
233
  def _reduce_9(val, _values)
243
- Compiler::SimpleSelector.new(node_type: val[0])
244
- end
245
-
246
- def _reduce_10(val, _values)
247
- Compiler::SimpleSelector.new(node_type: val[0], attribute_list: val[1])
248
- end
249
-
250
- def _reduce_11(val, _values)
251
234
  Compiler::AttributeList.new(attribute: val[1], rest: val[3])
252
235
  end
253
236
 
254
- def _reduce_12(val, _values)
237
+ def _reduce_10(val, _values)
255
238
  Compiler::AttributeList.new(attribute: val[1])
256
239
  end
257
240
 
258
- def _reduce_13(val, _values)
241
+ def _reduce_11(val, _values)
259
242
  Compiler::Attribute.new(key: val[0], value: val[2], operator: val[1])
260
243
  end
261
244
 
262
- def _reduce_14(val, _values)
245
+ def _reduce_12(val, _values)
263
246
  Compiler::Attribute.new(key: val[0], value: Compiler::Array.new, operator: val[1])
264
247
  end
265
248
 
266
- def _reduce_15(val, _values)
249
+ def _reduce_13(val, _values)
267
250
  Compiler::Attribute.new(key: val[0], value: val[3], operator: val[1])
268
251
  end
269
252
 
270
- def _reduce_16(val, _values)
253
+ def _reduce_14(val, _values)
271
254
  Compiler::Array.new(value: val[0], rest: val[1])
272
255
  end
273
256
 
274
- def _reduce_17(val, _values)
257
+ def _reduce_15(val, _values)
275
258
  Compiler::Array.new(value: val[0])
276
259
  end
277
260
 
278
- # reduce 18 omitted
261
+ # reduce 16 omitted
279
262
 
280
- def _reduce_19(val, _values)
263
+ def _reduce_17(val, _values)
281
264
  Compiler::DynamicAttribute.new(value: val[1])
282
265
  end
283
266
 
284
- def _reduce_20(val, _values)
267
+ def _reduce_18(val, _values)
285
268
  Compiler::Boolean.new(value: val[0])
286
269
  end
287
270
 
288
- def _reduce_21(val, _values)
271
+ def _reduce_19(val, _values)
289
272
  Compiler::Float.new(value: val[0])
290
273
  end
291
274
 
292
- def _reduce_22(val, _values)
275
+ def _reduce_20(val, _values)
293
276
  Compiler::Integer.new(value: val[0])
294
277
  end
295
278
 
296
- def _reduce_23(val, _values)
279
+ def _reduce_21(val, _values)
297
280
  Compiler::Nil.new(value: val[0])
298
281
  end
299
282
 
300
- def _reduce_24(val, _values)
283
+ def _reduce_22(val, _values)
301
284
  Compiler::Regexp.new(value: val[0])
302
285
  end
303
286
 
304
- def _reduce_25(val, _values)
287
+ def _reduce_23(val, _values)
305
288
  Compiler::String.new(value: val[0])
306
289
  end
307
290
 
308
- def _reduce_26(val, _values)
291
+ def _reduce_24(val, _values)
309
292
  Compiler::Symbol.new(value: val[0])
310
293
  end
311
294
 
312
- def _reduce_27(val, _values)
295
+ def _reduce_25(val, _values)
313
296
  Compiler::Identifier.new(value: val[0])
314
297
  end
315
298
 
@@ -1,8 +1,8 @@
1
1
  class Synvert::Core::NodeQuery::Parser
2
2
  options no_result_var
3
- token tNODE_TYPE tATTRIBUTE tKEY tIDENTIFIER tIDENTIFIER_VALUE tINDEX tPSEUDO_CLASS tRELATIONSHIP
3
+ token tNODE_TYPE tGOTO_SCOPE tATTRIBUTE tKEY tIDENTIFIER tIDENTIFIER_VALUE tPSEUDO_CLASS tRELATIONSHIP
4
4
  tOPEN_ATTRIBUTE tCLOSE_ATTRIBUTE tOPEN_DYNAMIC_ATTRIBUTE tCLOSE_DYNAMIC_ATTRIBUTE
5
- tOPEN_ARRAY tCLOSE_ARRAY tOPEN_SELECTOR tCLOSE_SELECTOR tOPEN_GOTO_SCOPE tCLOSE_GOTO_SCOPE
5
+ tOPEN_ARRAY tCLOSE_ARRAY tOPEN_SELECTOR tCLOSE_SELECTOR
6
6
  tOPERATOR tARRAY_VALUE tDYNAMIC_ATTRIBUTE tBOOLEAN tFLOAT tINTEGER tNIL tREGEXP tSTRING tSYMBOL
7
7
  rule
8
8
  expression
@@ -10,16 +10,14 @@ rule
10
10
  | selector { Compiler::Expression.new(selector: val[0]) }
11
11
 
12
12
  selector
13
- : simple_selector { Compiler::Selector.new(simple_selector: val[0]) }
14
- | simple_selector tINDEX { Compiler::Selector.new(simple_selector: val[0], index: val[1]) }
15
- | simple_selector tPSEUDO_CLASS tOPEN_SELECTOR selector tCLOSE_SELECTOR { Compiler::Selector.new(simple_selector: val[0], pseudo_class: val[1], pseudo_selector: val[3]) }
13
+ : basic_selector { Compiler::Selector.new(basic_selector: val[0]) }
16
14
  | tPSEUDO_CLASS tOPEN_SELECTOR selector tCLOSE_SELECTOR { Compiler::Selector.new(pseudo_class: val[0], pseudo_selector: val[2]) }
17
15
  | tRELATIONSHIP selector { Compiler::Selector.new(relationship: val[0], rest: val[1]) }
18
- | tOPEN_GOTO_SCOPE tIDENTIFIER tCLOSE_GOTO_SCOPE selector { Compiler::Selector.new(goto_scope: val[1], rest: val[3]) }
16
+ | tGOTO_SCOPE selector { Compiler::Selector.new(goto_scope: val[0], rest: val[1]) }
19
17
 
20
- simple_selector
21
- : tNODE_TYPE { Compiler::SimpleSelector.new(node_type: val[0]) }
22
- | tNODE_TYPE attribute_list { Compiler::SimpleSelector.new(node_type: val[0], attribute_list: val[1]) }
18
+ basic_selector
19
+ : tNODE_TYPE { Compiler::BasicSelector.new(node_type: val[0]) }
20
+ | tNODE_TYPE attribute_list { Compiler::BasicSelector.new(node_type: val[0], attribute_list: val[1]) }
23
21
 
24
22
  attribute_list
25
23
  : tOPEN_ATTRIBUTE attribute tCLOSE_ATTRIBUTE attribute_list { Compiler::AttributeList.new(attribute: val[1], rest: val[3]) }
@@ -35,7 +33,7 @@ rule
35
33
  | value { Compiler::Array.new(value: val[0]) }
36
34
 
37
35
  value
38
- : simple_selector
36
+ : basic_selector
39
37
  | tOPEN_DYNAMIC_ATTRIBUTE tDYNAMIC_ATTRIBUTE tCLOSE_DYNAMIC_ATTRIBUTE { Compiler::DynamicAttribute.new(value: val[1]) }
40
38
  | tBOOLEAN { Compiler::Boolean.new(value: val[0]) }
41
39
  | tFLOAT { Compiler::Float.new(value: val[0]) }
@@ -9,12 +9,10 @@
9
9
  # * attribute regex: <code>.send[key=~/\A:([^'"]+)\z/]</code>, <code>.send[key!~/\A:([^'"]+)\z/]</code>
10
10
  # * attribute conditions: +.send[message != nil]+, +.send[value > 1]+, +.send[value >= 1]+, +.send[value < 1]+, +.send[value <= 1]+
11
11
  # * nested attribute: +.send[caller.message = map]+, +.send[arguments.size = 2]+
12
- # * first or last child: +.def:first-child+, +.send:last-child+
13
- # * nth-child or nth-last-child: +.def:nth-child(2)+, +.send:nth-last-child(2)+
14
12
  # * descendant: +.class .send+
15
13
  # * child: +.class > .def+
16
- # * following sibling: <code>.def:first-child + .def</code>
17
- # * subsequnt sibling: +.def:first-child ~ .def+
14
+ # * following sibling: <code>.def + .def</code>
15
+ # * subsequnt sibling: +.def ~ .def+
18
16
  # * has: +.class:has(.def)+
19
17
  #
20
18
  # It also supports some custom selectors:
@@ -26,6 +24,7 @@
26
24
  # * NOT IN operator: +.send[message NOT IN (create build)]+
27
25
  # * INCLUDES operator: +.send[arguments INCLUDES &block]+
28
26
  # * dynamic attribute value: +.hash > .pair[key={{value}}]+
27
+ # * goto scope: +.class body > .def+
29
28
  #
30
29
  # @example
31
30
  # # it matches methods call nodes, like `puts message` or `p message`
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '1.3.1'
5
+ VERSION = '1.4.0'
6
6
  end
7
7
  end
@@ -502,64 +502,6 @@ module Synvert::Core::NodeQuery
502
502
  end
503
503
  end
504
504
 
505
- context 'position' do
506
- it 'matches :first-child' do
507
- source = '.send[arguments=:create]:first-child'
508
- expected_tokens = [
509
- [:tNODE_TYPE, "send"],
510
- [:tOPEN_ATTRIBUTE, "["],
511
- [:tKEY, "arguments"],
512
- [:tOPERATOR, "=="],
513
- [:tSYMBOL, :create],
514
- [:tCLOSE_ATTRIBUTE, "]"],
515
- [:tINDEX, 0]
516
- ]
517
- assert_tokens source, expected_tokens
518
- end
519
-
520
- it 'matches :last-child' do
521
- source = '.send[arguments=:create]:last-child'
522
- expected_tokens = [
523
- [:tNODE_TYPE, "send"],
524
- [:tOPEN_ATTRIBUTE, "["],
525
- [:tKEY, "arguments"],
526
- [:tOPERATOR, "=="],
527
- [:tSYMBOL, :create],
528
- [:tCLOSE_ATTRIBUTE, "]"],
529
- [:tINDEX, -1]
530
- ]
531
- assert_tokens source, expected_tokens
532
- end
533
-
534
- it 'matches :nth-child(1)' do
535
- source = '.send[arguments=:create]:nth-child(1)'
536
- expected_tokens = [
537
- [:tNODE_TYPE, "send"],
538
- [:tOPEN_ATTRIBUTE, "["],
539
- [:tKEY, "arguments"],
540
- [:tOPERATOR, "=="],
541
- [:tSYMBOL, :create],
542
- [:tCLOSE_ATTRIBUTE, "]"],
543
- [:tINDEX, 0]
544
- ]
545
- assert_tokens source, expected_tokens
546
- end
547
-
548
- it 'matches :nth-last-child(1)' do
549
- source = '.send[arguments=:create]:nth-last-child(1)'
550
- expected_tokens = [
551
- [:tNODE_TYPE, "send"],
552
- [:tOPEN_ATTRIBUTE, "["],
553
- [:tKEY, "arguments"],
554
- [:tOPERATOR, "=="],
555
- [:tSYMBOL, :create],
556
- [:tCLOSE_ATTRIBUTE, "]"],
557
- [:tINDEX, -1]
558
- ]
559
- assert_tokens source, expected_tokens
560
- end
561
- end
562
-
563
505
  context 'descendant' do
564
506
  it 'matches' do
565
507
  source = '.class .send'
@@ -624,12 +566,10 @@ module Synvert::Core::NodeQuery
624
566
 
625
567
  context 'goto_scope' do
626
568
  it 'matches' do
627
- source = '.block <body> > .def'
569
+ source = '.block body > .def'
628
570
  expected_tokens = [
629
571
  [:tNODE_TYPE, "block"],
630
- [:tOPEN_GOTO_SCOPE, "<"],
631
- [:tIDENTIFIER, "body"],
632
- [:tCLOSE_GOTO_SCOPE, ">"],
572
+ [:tGOTO_SCOPE, "body"],
633
573
  [:tRELATIONSHIP, ">"],
634
574
  [:tNODE_TYPE, "def"]
635
575
  ]
@@ -30,37 +30,17 @@ module Synvert::Core::NodeQuery
30
30
  end
31
31
 
32
32
  it 'parses scope' do
33
- source = '.block <body> > .send'
34
- assert_parser(source)
35
- end
36
-
37
- it 'parses :first-child' do
38
- source = '.class .def:first-child'
39
- assert_parser(source)
40
- end
41
-
42
- it 'parses :last-child' do
43
- source = '.class .def:last-child'
44
- assert_parser(source)
45
- end
46
-
47
- it 'parses :nth-child(n)' do
48
- source = '.class .def:nth-child(2)'
49
- assert_parser(source)
50
- end
51
-
52
- it 'parses :nth-last-child(n)' do
53
- source = '.class .def:nth-last-child(2)'
33
+ source = '.block body > .send'
54
34
  assert_parser(source)
55
35
  end
56
36
 
57
37
  it 'parses :has selector' do
58
- source = '.class:has(> .def)'
38
+ source = '.class :has(> .def)'
59
39
  assert_parser(source)
60
40
  end
61
41
 
62
42
  it 'parses :not_has selector' do
63
- source = '.class:not_has(> .def)'
43
+ source = '.class :not_has(> .def)'
64
44
  assert_parser(source)
65
45
  end
66
46
 
@@ -195,31 +175,6 @@ module Synvert::Core::NodeQuery
195
175
  expect(expression.query_nodes(node)).to eq node.body
196
176
  end
197
177
 
198
- it 'matches first def node' do
199
- expression = parser.parse('.def:first-child')
200
- expect(expression.query_nodes(node)).to eq [node.body.first]
201
- end
202
-
203
- it 'matches nested first node' do
204
- expression = parser.parse('.def[arguments.size=0] .send:first-child')
205
- expect(expression.query_nodes(node)).to eq [node.body.first.body.first, node.body.second.body.first]
206
- end
207
-
208
- it 'matches last def node' do
209
- expression = parser.parse('.def:last-child')
210
- expect(expression.query_nodes(node)).to eq [node.body.last]
211
- end
212
-
213
- it 'matches nth-child node' do
214
- expression = parser.parse('.def:nth-child(2)')
215
- expect(expression.query_nodes(node)).to eq [node.body.second]
216
- end
217
-
218
- it 'matches nth-last-child node' do
219
- expression = parser.parse('.def:nth-last-child(2)')
220
- expect(expression.query_nodes(node)).to eq [node.body[-2]]
221
- end
222
-
223
178
  it 'matches start with' do
224
179
  expression = parser.parse('.def[name^=foo]')
225
180
  expect(expression.query_nodes(node)).to eq [node.body.first, node.body.last]
@@ -297,15 +252,15 @@ module Synvert::Core::NodeQuery
297
252
  end
298
253
 
299
254
  it 'matches goto scope' do
300
- expression = parser.parse('.def <body> > .send[message=:create]')
255
+ expression = parser.parse('.def body > .send[message=:create]')
301
256
  expect(expression.query_nodes(node)).to eq [node.body.first.body.last, node.body.second.body.last]
302
257
 
303
- expression = parser.parse('.def <body> .send[message=:create]')
258
+ expression = parser.parse('.def body .send[message=:create]')
304
259
  expect(expression.query_nodes(node)).to eq [node.body.first.body.last, node.body.second.body.last]
305
260
  end
306
261
 
307
262
  it 'matches multiple goto scope' do
308
- expression = parser.parse('.block <caller.arguments> .const[name=Synvert]')
263
+ expression = parser.parse('.block caller.arguments .const[name=Synvert]')
309
264
  expect(expression.query_nodes(test_node)).to eq [test_node.caller.arguments.first]
310
265
  end
311
266
 
@@ -64,6 +64,13 @@ module Synvert::Core
64
64
  scope.process
65
65
  }.to raise_error(NodeQuery::Compiler::ParseError)
66
66
 
67
+ scope = described_class.new(instance, '.block <caller.arguments> .hash') {}
68
+ expect {
69
+ scope.process
70
+ }.to raise_error(NodeQuery::Compiler::ParseError)
71
+ end
72
+
73
+ it 'raises InvalidOperatorError' do
67
74
  scope = described_class.new(instance, '.send[receiver IN FactoryGirl]') {}
68
75
  expect {
69
76
  scope.process
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synvert-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-14 00:00:00.000000000 Z
11
+ date: 2022-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,6 +80,7 @@ files:
80
80
  - lib/synvert/core/node_query/compiler/array.rb
81
81
  - lib/synvert/core/node_query/compiler/attribute.rb
82
82
  - lib/synvert/core/node_query/compiler/attribute_list.rb
83
+ - lib/synvert/core/node_query/compiler/basic_selector.rb
83
84
  - lib/synvert/core/node_query/compiler/boolean.rb
84
85
  - lib/synvert/core/node_query/compiler/comparable.rb
85
86
  - lib/synvert/core/node_query/compiler/dynamic_attribute.rb
@@ -92,7 +93,6 @@ files:
92
93
  - lib/synvert/core/node_query/compiler/parse_error.rb
93
94
  - lib/synvert/core/node_query/compiler/regexp.rb
94
95
  - lib/synvert/core/node_query/compiler/selector.rb
95
- - lib/synvert/core/node_query/compiler/simple_selector.rb
96
96
  - lib/synvert/core/node_query/compiler/string.rb
97
97
  - lib/synvert/core/node_query/compiler/symbol.rb
98
98
  - lib/synvert/core/node_query/lexer.rex