synvert-core 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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