synvert-core 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -4
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile +0 -3
  5. data/Guardfile +0 -9
  6. data/README.md +30 -12
  7. data/Rakefile +1 -15
  8. data/lib/synvert/core/engine/erb.rb +1 -1
  9. data/lib/synvert/core/engine.rb +1 -1
  10. data/lib/synvert/core/node_ext.rb +0 -466
  11. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +20 -17
  12. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -1
  13. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -1
  14. data/lib/synvert/core/rewriter/instance.rb +83 -133
  15. data/lib/synvert/core/rewriter/scope/query_scope.rb +2 -2
  16. data/lib/synvert/core/rewriter/scope/within_scope.rb +4 -4
  17. data/lib/synvert/core/rewriter.rb +0 -10
  18. data/lib/synvert/core/version.rb +1 -1
  19. data/lib/synvert/core.rb +4 -6
  20. data/spec/synvert/core/engine/erb_spec.rb +3 -3
  21. data/spec/synvert/core/node_ext_spec.rb +0 -795
  22. data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +21 -1
  23. data/spec/synvert/core/rewriter/instance_spec.rb +47 -115
  24. data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -4
  25. data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +1 -4
  26. data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +1 -4
  27. data/synvert-core-ruby.gemspec +4 -2
  28. metadata +44 -61
  29. data/lib/synvert/core/array_ext.rb +0 -48
  30. data/lib/synvert/core/node_query/compiler/array.rb +0 -34
  31. data/lib/synvert/core/node_query/compiler/attribute.rb +0 -39
  32. data/lib/synvert/core/node_query/compiler/attribute_list.rb +0 -24
  33. data/lib/synvert/core/node_query/compiler/basic_selector.rb +0 -28
  34. data/lib/synvert/core/node_query/compiler/boolean.rb +0 -23
  35. data/lib/synvert/core/node_query/compiler/comparable.rb +0 -86
  36. data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +0 -51
  37. data/lib/synvert/core/node_query/compiler/expression.rb +0 -41
  38. data/lib/synvert/core/node_query/compiler/float.rb +0 -23
  39. data/lib/synvert/core/node_query/compiler/identifier.rb +0 -41
  40. data/lib/synvert/core/node_query/compiler/integer.rb +0 -23
  41. data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +0 -7
  42. data/lib/synvert/core/node_query/compiler/nil.rb +0 -23
  43. data/lib/synvert/core/node_query/compiler/parse_error.rb +0 -7
  44. data/lib/synvert/core/node_query/compiler/regexp.rb +0 -37
  45. data/lib/synvert/core/node_query/compiler/selector.rb +0 -113
  46. data/lib/synvert/core/node_query/compiler/string.rb +0 -23
  47. data/lib/synvert/core/node_query/compiler/symbol.rb +0 -23
  48. data/lib/synvert/core/node_query/compiler.rb +0 -25
  49. data/lib/synvert/core/node_query/lexer.rex +0 -99
  50. data/lib/synvert/core/node_query/lexer.rex.rb +0 -299
  51. data/lib/synvert/core/node_query/parser.racc.rb +0 -306
  52. data/lib/synvert/core/node_query/parser.y +0 -60
  53. data/lib/synvert/core/node_query.rb +0 -36
  54. data/lib/synvert/core/rewriter/action/append_action.rb +0 -28
  55. data/lib/synvert/core/rewriter/action/delete_action.rb +0 -34
  56. data/lib/synvert/core/rewriter/action/insert_action.rb +0 -34
  57. data/lib/synvert/core/rewriter/action/insert_after_action.rb +0 -22
  58. data/lib/synvert/core/rewriter/action/prepend_action.rb +0 -44
  59. data/lib/synvert/core/rewriter/action/remove_action.rb +0 -56
  60. data/lib/synvert/core/rewriter/action/replace_action.rb +0 -33
  61. data/lib/synvert/core/rewriter/action/replace_with_action.rb +0 -36
  62. data/lib/synvert/core/rewriter/action/wrap_action.rb +0 -37
  63. data/lib/synvert/core/rewriter/action.rb +0 -102
  64. data/spec/synvert/core/node_query/lexer_spec.rb +0 -580
  65. data/spec/synvert/core/node_query/parser_spec.rb +0 -337
  66. data/spec/synvert/core/rewriter/action/append_action_spec.rb +0 -70
  67. data/spec/synvert/core/rewriter/action/delete_action_spec.rb +0 -26
  68. data/spec/synvert/core/rewriter/action/insert_action_spec.rb +0 -70
  69. data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +0 -26
  70. data/spec/synvert/core/rewriter/action/prepend_action_spec.rb +0 -175
  71. data/spec/synvert/core/rewriter/action/remove_action_spec.rb +0 -26
  72. data/spec/synvert/core/rewriter/action/replace_action_spec.rb +0 -28
  73. data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +0 -59
  74. data/spec/synvert/core/rewriter/action/wrap_action_spec.rb +0 -31
  75. data/spec/synvert/core/rewriter/action_spec.rb +0 -14
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Compare acutal value with expected value.
5
- module Comparable
6
- SIMPLE_VALID_OPERATORS = ['==', '!=', 'includes']
7
- STRING_VALID_OPERATORS = ['==', '!=', '^=', '$=', '*=', 'includes']
8
- NUMBER_VALID_OPERATORS = ['==', '!=', '>', '>=', '<', '<=', 'includes']
9
- ARRAY_VALID_OPERATORS = ['==', '!=', 'in', 'not_in']
10
- REGEXP_VALID_OPERATORS = ['=~', '!~']
11
-
12
- # Check if the actual value matches the expected value.
13
- #
14
- # @param node [Parser::AST::Node] node to calculate actual value
15
- # @param operator [Symbol] operator to compare with expected value, operator can be <code>'=='</code>, <code>'!='</code>, <code>'>'</code>, <code>'>='</code>, <code>'<'</code>, <code>'<='</code>, <code>'includes'</code>, <code>'in'</code>, <code>'not_in'</code>, <code>'=~'</code>, <code>'!~'</code>
16
- # @return [Boolean] true if actual value matches the expected value
17
- # @raise [Synvert::Core::NodeQuery::Compiler::InvalidOperatorError] if operator is invalid
18
- def match?(node, operator)
19
- raise InvalidOperatorError, "invalid operator #{operator}" unless valid_operator?(operator)
20
-
21
- case operator
22
- when '!='
23
- if expected_value.is_a?(::Array)
24
- actual = actual_value(node)
25
- !actual.is_a?(::Array) || actual.size != expected_value.size ||
26
- actual.zip(expected_value).any? { |actual_node, expected_node| expected_node.match?(actual_node, '!=') }
27
- else
28
- actual_value(node) != expected_value
29
- end
30
- when '=~'
31
- actual_value(node) =~ expected_value
32
- when '!~'
33
- actual_value(node) !~ expected_value
34
- when '^='
35
- actual_value(node).start_with?(expected_value)
36
- when '$='
37
- actual_value(node).end_with?(expected_value)
38
- when '*='
39
- actual_value(node).include?(expected_value)
40
- when '>'
41
- actual_value(node) > expected_value
42
- when '>='
43
- actual_value(node) >= expected_value
44
- when '<'
45
- actual_value(node) < expected_value
46
- when '<='
47
- actual_value(node) <= expected_value
48
- when 'in'
49
- expected_value.any? { |expected| expected.match?(node, '==') }
50
- when 'not_in'
51
- expected_value.all? { |expected| expected.match?(node, '!=') }
52
- when 'includes'
53
- actual_value(node).any? { |actual| actual == expected_value }
54
- else
55
- if expected_value.is_a?(::Array)
56
- actual = actual_value(node)
57
- actual.is_a?(::Array) && actual.size == expected_value.size &&
58
- actual.zip(expected_value).all? { |actual_node, expected_node| expected_node.match?(actual_node, '==') }
59
- else
60
- actual_value(node) == expected_value
61
- end
62
- end
63
- end
64
-
65
- # Get the actual value from ast node.
66
- # @return if node is a {Parser::AST::Node}, return the node value, otherwise, return the node itself.
67
- def actual_value(node)
68
- if node.is_a?(::Parser::AST::Node)
69
- node.to_value
70
- else
71
- node
72
- end
73
- end
74
-
75
- # Get the expected value
76
- def expected_value
77
- @value
78
- end
79
-
80
- # Check if the operator is valid.
81
- # @return [Boolean] true if the operator is valid
82
- def valid_operator?(operator)
83
- valid_operators.include?(operator)
84
- end
85
- end
86
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # DynamicAttribute represents a ruby dynamic attribute.
5
- # e.g. code is <code>{ a: a }</code>, query is <code>'.hash > .pair[key={{value}}]'</code>,
6
- # <code>{{value}}</code> is the dynamic attribute.
7
- class DynamicAttribute
8
- include Comparable
9
-
10
- attr_accessor :base_node
11
-
12
- # Initialize a DynamicAttribute.
13
- # @param value [String] the dynamic attribute value
14
- def initialize(value:)
15
- @value = value
16
- end
17
-
18
- # Get the actual value of a node.
19
- #
20
- # @param node the node
21
- # @return [String] if node is a {Parser::AST::Node}, return the node source code, otherwise return the node itself.
22
- def actual_value(node)
23
- if node.is_a?(::Parser::AST::Node)
24
- node.to_source
25
- else
26
- node
27
- end
28
- end
29
-
30
- # Get the expected value.
31
- #
32
- # @return [String] Query the node by @valud from base_node, if the node is a {Parser::AST::Node}, return the node source code, otherwise return the node itself.
33
- def expected_value
34
- node = base_node.child_node_by_name(@value)
35
- if node.is_a?(::Parser::AST::Node)
36
- node.to_source
37
- else
38
- node
39
- end
40
- end
41
-
42
- # Get valid operators.
43
- def valid_operators
44
- SIMPLE_VALID_OPERATORS
45
- end
46
-
47
- def to_s
48
- "{{#{@value}}}"
49
- end
50
- end
51
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Expression represents a node query expression.
5
- class Expression
6
- # Initialize a Expression.
7
- # @param selector [Synvert::Core::NodeQuery::Compiler::Selector] the selector
8
- # @param rest [Synvert::Core::NodeQuery::Compiler::Expression] the rest expression
9
- def initialize(selector: nil, rest: nil)
10
- @selector = selector
11
- @rest = rest
12
- end
13
-
14
- # Check if the node matches the expression.
15
- # @param node [Parser::AST::Node] the node
16
- # @return [Boolean]
17
- def match?(node)
18
- !query_nodes(node).empty?
19
- end
20
-
21
- # Query nodes by the selector and the rest expression.
22
- #
23
- # @param node [Parser::AST::Node] node to match
24
- # @return [Array<Parser::AST::Node>] matching nodes.
25
- def query_nodes(node)
26
- matching_nodes = @selector.query_nodes(node)
27
- return matching_nodes if @rest.nil?
28
-
29
- matching_nodes.flat_map do |matching_node|
30
- @rest.query_nodes(matching_node)
31
- end
32
- end
33
-
34
- def to_s
35
- result = []
36
- result << @selector.to_s if @selector
37
- result << @rest.to_s if @rest
38
- result.join(' ')
39
- end
40
- end
41
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Float represents a ruby float value.
5
- class Float
6
- include Comparable
7
-
8
- # Initialize a Float.
9
- # @param value [Float] the float value
10
- def initialize(value:)
11
- @value = value
12
- end
13
-
14
- # Get valid operators.
15
- def valid_operators
16
- NUMBER_VALID_OPERATORS
17
- end
18
-
19
- def to_s
20
- @value.to_s
21
- end
22
- end
23
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Identifier represents a ruby identifier value.
5
- # e.g. code is `class Synvert; end`, `Synvert` is an identifier.
6
- class Identifier
7
- include Comparable
8
-
9
- # Initialize an Identifier.
10
- # @param value [String] the identifier value
11
- def initialize(value:)
12
- @value = value
13
- end
14
-
15
- # Get the actual value.
16
- #
17
- # @param node the node
18
- # @return [String|Array]
19
- # If the node is a {Parser::AST::Node}, return the node source code,
20
- # if the node is an Array, return the array of each element's actual value,
21
- # otherwise, return the String value.
22
- def actual_value(node)
23
- if node.is_a?(::Parser::AST::Node)
24
- node.to_source
25
- elsif node.is_a?(::Array)
26
- node.map { |n| actual_value(n) }
27
- else
28
- node.to_s
29
- end
30
- end
31
-
32
- # Get valid operators.
33
- def valid_operators
34
- STRING_VALID_OPERATORS
35
- end
36
-
37
- def to_s
38
- @value
39
- end
40
- end
41
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Integer represents a ruby integer value.
5
- class Integer
6
- include Comparable
7
-
8
- # Initialize a Integer.
9
- # @param value [Integer] the integer value
10
- def initialize(value:)
11
- @value = value
12
- end
13
-
14
- # Get valid operators.
15
- def valid_operators
16
- NUMBER_VALID_OPERATORS
17
- end
18
-
19
- def to_s
20
- @value.to_s
21
- end
22
- end
23
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Operator is invalid error.
5
- class InvalidOperatorError < StandardError
6
- end
7
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Nil represents a ruby nil value.
5
- class Nil
6
- include Comparable
7
-
8
- # Initialize a Nil.
9
- # @param value [nil] the nil value
10
- def initialize(value:)
11
- @value = value
12
- end
13
-
14
- # Get valid operators.
15
- def valid_operators
16
- SIMPLE_VALID_OPERATORS
17
- end
18
-
19
- def to_s
20
- 'nil'
21
- end
22
- end
23
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # The parser error.
5
- class ParseError < StandardError
6
- end
7
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Regexp represents a ruby regexp value.
5
- class Regexp
6
- include Comparable
7
-
8
- # Initialize a Regexp.
9
- # @param value [Regexp] the regexp value
10
- def initialize(value:)
11
- @value = value
12
- end
13
-
14
- # Check if the regexp value matches the node value.
15
- # @param node [Parser::AST::Node] the node
16
- # @param operator [Symbol] the operator
17
- # @return [Boolean] true if the regexp value matches the node value, otherwise, false.
18
- def match?(node, operator = '=~')
19
- match =
20
- if node.is_a?(::Parser::AST::Node)
21
- @value.match(node.to_source)
22
- else
23
- @value.match(node.to_s)
24
- end
25
- operator == '=~' ? match : !match
26
- end
27
-
28
- # Get valid operators.
29
- def valid_operators
30
- REGEXP_VALID_OPERATORS
31
- end
32
-
33
- def to_s
34
- @value.to_s
35
- end
36
- end
37
- end
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Selector used to match nodes, it combines by node type and/or attribute list, plus index or has expression.
5
- class Selector
6
- # Initialize a Selector.
7
- # @param goto_scope [String] goto scope
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
- # @param rest [Synvert::Core::NodeQuery::Compiler::Selector] the rest selector
10
- # @param basic_selector [Synvert::Core::NodeQuery::Compiler::BasicSelector] the simple selector
11
- # @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
12
- # @param pseudo_class [String] the pseudo class, can be <code>has</code> or <code>not_has</code>
13
- # @param pseudo_selector [Synvert::Core::NodeQuery::Compiler::Expression] the pseudo selector
14
- def initialize(goto_scope: nil, relationship: nil, rest: nil, basic_selector: nil, pseudo_class: nil, pseudo_selector: nil)
15
- @goto_scope = goto_scope
16
- @relationship = relationship
17
- @rest = rest
18
- @basic_selector = basic_selector
19
- @pseudo_class = pseudo_class
20
- @pseudo_selector = pseudo_selector
21
- end
22
-
23
- # Check if node matches the selector.
24
- # @param node [Parser::AST::Node] the node
25
- def match?(node)
26
- node.is_a?(::Parser::AST::Node) && (!@basic_selector || @basic_selector.match?(node)) && match_pseudo_class?(node)
27
- end
28
-
29
- # Query nodes by the selector.
30
- #
31
- # * If relationship is nil, it will match in all recursive child nodes and return matching nodes.
32
- # * If relationship is decendant, it will match in all recursive child nodes.
33
- # * If relationship is child, it will match in direct child nodes.
34
- # * If relationship is next sibling, it try to match next sibling node.
35
- # * If relationship is subsequent sibling, it will match in all sibling nodes.
36
- # @param node [Parser::AST::Node] node to match
37
- # @return [Array<Parser::AST::Node>] matching nodes.
38
- def query_nodes(node)
39
- return find_nodes_by_relationship(node) if @relationship
40
-
41
- if node.is_a?(::Array)
42
- return node.flat_map { |child_node| query_nodes(child_node) }
43
- end
44
-
45
- return find_nodes_by_goto_scope(node) if @goto_scope
46
-
47
- nodes = []
48
- nodes << node if match?(node)
49
- if @basic_selector
50
- node.recursive_children do |child_node|
51
- nodes << child_node if match?(child_node)
52
- end
53
- end
54
- nodes
55
- end
56
-
57
- def to_s
58
- result = []
59
- result << "#{@goto_scope} " if @goto_scope
60
- result << "#{@relationship} " if @relationship
61
- result << @rest.to_s if @rest
62
- result << @basic_selector.to_s if @basic_selector
63
- result << ":#{@pseudo_class}(#{@pseudo_selector})" if @pseudo_class
64
- result.join('')
65
- end
66
-
67
- private
68
-
69
- # Find nodes by @goto_scope
70
- # @param node [Parser::AST::Node] node to match
71
- def find_nodes_by_goto_scope(node)
72
- @goto_scope.split('.').each { |scope| node = node.send(scope) }
73
- @rest.query_nodes(node)
74
- end
75
-
76
- # Find ndoes by @relationship
77
- # @param node [Parser::AST::Node] node to match
78
- def find_nodes_by_relationship(node)
79
- nodes = []
80
- case @relationship
81
- when '>'
82
- if node.is_a?(::Array)
83
- node.each do |child_node|
84
- nodes << child_node if @rest.match?(child_node)
85
- end
86
- else
87
- node.children.each do |child_node|
88
- nodes << child_node if @rest.match?(child_node)
89
- end
90
- end
91
- when '+'
92
- next_sibling = node.siblings.first
93
- nodes << next_sibling if @rest.match?(next_sibling)
94
- when '~'
95
- node.siblings.each do |sibling_node|
96
- nodes << sibling_node if @rest.match?(sibling_node)
97
- end
98
- end
99
- nodes
100
- end
101
-
102
- def match_pseudo_class?(node)
103
- case @pseudo_class
104
- when 'has'
105
- !@pseudo_selector.query_nodes(node).empty?
106
- when 'not_has'
107
- @pseudo_selector.query_nodes(node).empty?
108
- else
109
- true
110
- end
111
- end
112
- end
113
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # String represents a ruby string value.
5
- class String
6
- include Comparable
7
-
8
- # Initialize a String.
9
- # @param value [String] the string value
10
- def initialize(value:)
11
- @value = value
12
- end
13
-
14
- # Get valid operators.
15
- def valid_operators
16
- STRING_VALID_OPERATORS
17
- end
18
-
19
- def to_s
20
- "\"#{@value}\""
21
- end
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- # Symbol represents a ruby symbol value.
5
- class Symbol
6
- include Comparable
7
-
8
- # Initliaze a Symobol.
9
- # @param value [Symbol] the symbol value
10
- def initialize(value:)
11
- @value = value
12
- end
13
-
14
- # Get valid operators.
15
- def valid_operators
16
- SIMPLE_VALID_OPERATORS
17
- end
18
-
19
- def to_s
20
- ":#{@value}"
21
- end
22
- end
23
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Synvert::Core::NodeQuery::Compiler
4
- autoload :InvalidOperatorError, 'synvert/core/node_query/compiler/invalid_operator_error'
5
- autoload :ParseError, 'synvert/core/node_query/compiler/parse_error'
6
-
7
- autoload :Comparable, 'synvert/core/node_query/compiler/comparable'
8
-
9
- autoload :Expression, 'synvert/core/node_query/compiler/expression'
10
- autoload :Selector, 'synvert/core/node_query/compiler/selector'
11
- autoload :BasicSelector, 'synvert/core/node_query/compiler/basic_selector'
12
- autoload :AttributeList, 'synvert/core/node_query/compiler/attribute_list'
13
- autoload :Attribute, 'synvert/core/node_query/compiler/attribute'
14
-
15
- autoload :Array, 'synvert/core/node_query/compiler/array'
16
- autoload :Boolean, 'synvert/core/node_query/compiler/boolean'
17
- autoload :DynamicAttribute, 'synvert/core/node_query/compiler/dynamic_attribute'
18
- autoload :Float, 'synvert/core/node_query/compiler/float'
19
- autoload :Identifier, 'synvert/core/node_query/compiler/identifier'
20
- autoload :Integer, 'synvert/core/node_query/compiler/integer'
21
- autoload :Nil, 'synvert/core/node_query/compiler/nil'
22
- autoload :Regexp, 'synvert/core/node_query/compiler/regexp'
23
- autoload :String, 'synvert/core/node_query/compiler/string'
24
- autoload :Symbol, 'synvert/core/node_query/compiler/symbol'
25
- end
@@ -1,99 +0,0 @@
1
- class Synvert::Core::NodeQuery::Lexer
2
-
3
- macros
4
- OPEN_ATTRIBUTE /\[/
5
- CLOSE_ATTRIBUTE /\]/
6
- OPEN_ARRAY /\(/
7
- CLOSE_ARRAY /\)/
8
- OPEN_SELECTOR /\(/
9
- CLOSE_SELECTOR /\)/
10
- OPEN_DYNAMIC_ATTRIBUTE /{{/
11
- CLOSE_DYNAMIC_ATTRIBUTE /}}/
12
- NODE_TYPE /\.[a-z]+/
13
- IDENTIFIER /[\.\w]+/
14
- IDENTIFIER_VALUE /[\.\w!&:\?<>=]+/
15
- FALSE /false/
16
- FLOAT /\d+\.\d+/
17
- INTEGER /\d+/
18
- NIL /nil/
19
- REGEXP_BODY /(?:[^\/]|\\\/)*/
20
- REGEXP /\/(#{REGEXP_BODY})(?<!\\)\/([imxo]*)/
21
- SYMBOL /:[\w!\?<>=]+/
22
- TRUE /true/
23
- SINGLE_QUOTE_STRING /'.*?'/
24
- DOUBLE_QUOTE_STRING /".*?"/
25
-
26
- rules
27
-
28
- # [:state] pattern [actions]
29
- /\s+/
30
- /:has/ { [:tPSEUDO_CLASS, text[1..-1]] }
31
- /:not_has/ { [:tPSEUDO_CLASS, text[1..-1]] }
32
- /#{NODE_TYPE}/ { [:tNODE_TYPE, text[1..]] }
33
- /#{IDENTIFIER}/ { [:tGOTO_SCOPE, text] }
34
- />/ { [:tRELATIONSHIP, text] }
35
- /~/ { [:tRELATIONSHIP, text] }
36
- /\+/ { [:tRELATIONSHIP, text] }
37
- /#{OPEN_SELECTOR}/ { [:tOPEN_SELECTOR, text] }
38
- /#{CLOSE_SELECTOR}/ { [:tCLOSE_SELECTOR, text] }
39
- /#{OPEN_ATTRIBUTE}/ { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
40
- :KEY /\s+/
41
- :KEY /\^=/ { @state = :VALUE; [:tOPERATOR, '^='] }
42
- :KEY /\$=/ { @state = :VALUE; [:tOPERATOR, '$='] }
43
- :KEY /\*=/ { @state = :VALUE; [:tOPERATOR, '*='] }
44
- :KEY /!=/ { @state = :VALUE; [:tOPERATOR, '!='] }
45
- :KEY /=~/ { @state = :VALUE; [:tOPERATOR, '=~'] }
46
- :KEY /!~/ { @state = :VALUE; [:tOPERATOR, '!~'] }
47
- :KEY />=/ { @state = :VALUE; [:tOPERATOR, '>='] }
48
- :KEY /<=/ { @state = :VALUE; [:tOPERATOR, '<='] }
49
- :KEY />/ { @state = :VALUE; [:tOPERATOR, '>'] }
50
- :KEY /</ { @state = :VALUE; [:tOPERATOR, '<'] }
51
- :KEY /=/ { @state = :VALUE; [:tOPERATOR, '=='] }
52
- :KEY /includes/i { @state = :VALUE; [:tOPERATOR, 'includes'] }
53
- :KEY /not in/i { @state = :VALUE; [:tOPERATOR, 'not_in'] }
54
- :KEY /in/i { @state = :VALUE; [:tOPERATOR, 'in'] }
55
- :KEY /#{IDENTIFIER}/ { [:tKEY, text] }
56
- :VALUE /\s+/
57
- :VALUE /\[\]=/ { [:tIDENTIFIER_VALUE, text] }
58
- :VALUE /\[\]/ { [:tIDENTIFIER_VALUE, text] }
59
- :VALUE /:\[\]=/ { [:tSYMBOL, text[1..-1].to_sym] }
60
- :VALUE /:\[\]/ { [:tSYMBOL, text[1..-1].to_sym] }
61
- :VALUE /#{OPEN_DYNAMIC_ATTRIBUTE}/ { @state = :DYNAMIC_ATTRIBUTE; [:tOPEN_DYNAMIC_ATTRIBUTE, text] }
62
- :VALUE /#{OPEN_ARRAY}/ { @state = :ARRAY_VALUE; [:tOPEN_ARRAY, text] }
63
- :VALUE /#{CLOSE_ATTRIBUTE}/ { @nested_count -= 1; @state = @nested_count == 0 ? nil : :VALUE; [:tCLOSE_ATTRIBUTE, text] }
64
- :VALUE /#{NIL}\?/ { [:tIDENTIFIER_VALUE, text] }
65
- :VALUE /#{NIL}/ { [:tNIL, nil] }
66
- :VALUE /#{TRUE}/ { [:tBOOLEAN, true] }
67
- :VALUE /#{FALSE}/ { [:tBOOLEAN, false] }
68
- :VALUE /#{SYMBOL}/ { [:tSYMBOL, text[1..-1].to_sym] }
69
- :VALUE /#{FLOAT}/ { [:tFLOAT, text.to_f] }
70
- :VALUE /#{INTEGER}/ { [:tINTEGER, text.to_i] }
71
- :VALUE /#{REGEXP}/ { [:tREGEXP, eval(text)] }
72
- :VALUE /#{DOUBLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
73
- :VALUE /#{SINGLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
74
- :VALUE /#{NODE_TYPE}/ { [:tNODE_TYPE, text[1..]] }
75
- :VALUE /#{OPEN_ATTRIBUTE}/ { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
76
- :VALUE /#{IDENTIFIER_VALUE}/ { [:tIDENTIFIER_VALUE, text] }
77
- :DYNAMIC_ATTRIBUTE /#{CLOSE_DYNAMIC_ATTRIBUTE}/ { @state = :VALUE; [:tCLOSE_DYNAMIC_ATTRIBUTE, text] }
78
- :DYNAMIC_ATTRIBUTE /#{IDENTIFIER}/ { [:tDYNAMIC_ATTRIBUTE, text] }
79
- :ARRAY_VALUE /\s+/
80
- :ARRAY_VALUE /#{CLOSE_ARRAY}/ { @state = :VALUE; [:tCLOSE_ARRAY, text] }
81
- :ARRAY_VALUE /#{NIL}\?/ { [:tIDENTIFIER_VALUE, text] }
82
- :ARRAY_VALUE /#{NIL}/ { [:tNIL, nil] }
83
- :ARRAY_VALUE /#{TRUE}/ { [:tBOOLEAN, true] }
84
- :ARRAY_VALUE /#{FALSE}/ { [:tBOOLEAN, false] }
85
- :ARRAY_VALUE /#{SYMBOL}/ { [:tSYMBOL, text[1..-1].to_sym] }
86
- :ARRAY_VALUE /#{FLOAT}/ { [:tFLOAT, text.to_f] }
87
- :ARRAY_VALUE /#{INTEGER}/ { [:tINTEGER, text.to_i] }
88
- :ARRAY_VALUE /#{REGEXP}/ { [:tREGEXP, eval(text)] }
89
- :ARRAY_VALUE /#{DOUBLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
90
- :ARRAY_VALUE /#{SINGLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
91
- :ARRAY_VALUE /#{IDENTIFIER_VALUE}/ { [:tIDENTIFIER_VALUE, text] }
92
-
93
- inner
94
- def initialize
95
- @nested_count = 0
96
- end
97
-
98
- def do_parse; end
99
- end