synvert-core 0.64.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -1
- data/.gitignore +4 -0
- data/CHANGELOG.md +5 -0
- data/Guardfile +11 -2
- data/README.md +2 -2
- data/Rakefile +15 -1
- data/lib/synvert/core/array_ext.rb +41 -0
- data/lib/synvert/core/engine/erb.rb +9 -8
- data/lib/synvert/core/node_ext.rb +47 -44
- data/lib/synvert/core/node_query/compiler/array.rb +34 -0
- data/lib/synvert/core/node_query/compiler/attribute.rb +51 -0
- data/lib/synvert/core/node_query/compiler/attribute_list.rb +24 -0
- data/lib/synvert/core/node_query/compiler/boolean.rb +23 -0
- data/lib/synvert/core/node_query/compiler/comparable.rb +79 -0
- data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +51 -0
- data/lib/synvert/core/node_query/compiler/expression.rb +88 -0
- data/lib/synvert/core/node_query/compiler/float.rb +23 -0
- data/lib/synvert/core/node_query/compiler/identifier.rb +41 -0
- data/lib/synvert/core/node_query/compiler/integer.rb +23 -0
- data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +7 -0
- data/lib/synvert/core/node_query/compiler/nil.rb +23 -0
- data/lib/synvert/core/node_query/compiler/parse_error.rb +7 -0
- data/lib/synvert/core/node_query/compiler/regexp.rb +37 -0
- data/lib/synvert/core/node_query/compiler/selector.rb +51 -0
- data/lib/synvert/core/node_query/compiler/string.rb +34 -0
- data/lib/synvert/core/node_query/compiler/symbol.rb +23 -0
- data/lib/synvert/core/node_query/compiler.rb +24 -0
- data/lib/synvert/core/node_query/lexer.rex +96 -0
- data/lib/synvert/core/node_query/lexer.rex.rb +293 -0
- data/lib/synvert/core/node_query/parser.racc.rb +518 -0
- data/lib/synvert/core/node_query/parser.y +84 -0
- data/lib/synvert/core/node_query.rb +36 -0
- data/lib/synvert/core/rewriter/action/delete_action.rb +4 -2
- data/lib/synvert/core/rewriter/action/replace_action.rb +4 -2
- data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +2 -2
- data/lib/synvert/core/rewriter/action/wrap_action.rb +3 -2
- data/lib/synvert/core/rewriter/action.rb +2 -1
- data/lib/synvert/core/rewriter/helper.rb +5 -2
- data/lib/synvert/core/rewriter/instance.rb +25 -13
- data/lib/synvert/core/rewriter/scope/query_scope.rb +36 -0
- data/lib/synvert/core/rewriter/scope/within_scope.rb +1 -1
- data/lib/synvert/core/rewriter.rb +1 -0
- data/lib/synvert/core/version.rb +1 -1
- data/lib/synvert/core.rb +22 -5
- data/spec/synvert/core/engine/erb_spec.rb +2 -2
- data/spec/synvert/core/node_ext_spec.rb +36 -5
- data/spec/synvert/core/node_query/lexer_spec.rb +512 -0
- data/spec/synvert/core/node_query/parser_spec.rb +270 -0
- data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +1 -6
- data/spec/synvert/core/rewriter/helper_spec.rb +4 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +24 -3
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +74 -0
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +12 -9
- data/spec/synvert/core/rewriter_spec.rb +4 -2
- data/synvert-core-ruby.gemspec +5 -1
- metadata +75 -2
@@ -0,0 +1,88 @@
|
|
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
|
+
# @param relationship [Symbol] the relationship between the selector and rest expression, it can be <code>:descendant</code>, <code>:child</code>, <code>:next_sibling</code>, <code>:subsequent_sibling</code> or <code>nil</code>.
|
10
|
+
def initialize(selector: nil, rest: nil, relationship: nil)
|
11
|
+
@selector = selector
|
12
|
+
@rest = rest
|
13
|
+
@relationship = relationship
|
14
|
+
end
|
15
|
+
|
16
|
+
# Check if the node matches the expression.
|
17
|
+
# @param node [Parser::AST::Node] the node
|
18
|
+
# @return [Boolean]
|
19
|
+
def match?(node)
|
20
|
+
!query_nodes(node).empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
# Query nodes by the expression.
|
24
|
+
#
|
25
|
+
# * If relationship is nil, it will match in all recursive child nodes and return matching nodes.
|
26
|
+
# * If relationship is :decendant, it will match in all recursive child nodes.
|
27
|
+
# * If relationship is :child, it will match in direct child nodes.
|
28
|
+
# * If relationship is :next_sibling, it try to match next sibling node.
|
29
|
+
# * If relationship is :subsequent_sibling, it will match in all sibling nodes.
|
30
|
+
# @param node [Parser::AST::Node] node to match
|
31
|
+
# @param descendant_match [Boolean] whether to match in descendant node
|
32
|
+
# @return [Array<Parser::AST::Node>] matching nodes.
|
33
|
+
def query_nodes(node, descendant_match: true)
|
34
|
+
matching_nodes = find_nodes_without_relationship(node, descendant_match: descendant_match)
|
35
|
+
if @relationship.nil?
|
36
|
+
return matching_nodes
|
37
|
+
end
|
38
|
+
|
39
|
+
expression_nodes = matching_nodes.map do |matching_node|
|
40
|
+
case @relationship
|
41
|
+
when :descendant
|
42
|
+
nodes = []
|
43
|
+
matching_node.recursive_children { |child_node|
|
44
|
+
nodes += @rest.query_nodes(child_node, descendant_match: false)
|
45
|
+
}
|
46
|
+
nodes
|
47
|
+
when :child
|
48
|
+
matching_node.children.map { |child_node| @rest.query_nodes(child_node, descendant_match: false) }
|
49
|
+
.flatten
|
50
|
+
when :next_sibling
|
51
|
+
@rest.query_nodes(matching_node.siblings.first, descendant_match: false)
|
52
|
+
when :subsequent_sibling
|
53
|
+
matching_node.siblings.map { |sibling_node| @rest.query_nodes(sibling_node, descendant_match: false) }
|
54
|
+
.flatten
|
55
|
+
end
|
56
|
+
end.flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
return @selector.to_s unless @rest
|
61
|
+
|
62
|
+
result = []
|
63
|
+
result << @selector if @selector
|
64
|
+
case @relationship
|
65
|
+
when :child then result << '>'
|
66
|
+
when :subsequent_sibling then result << '~'
|
67
|
+
when :next_sibling then result << '+'
|
68
|
+
end
|
69
|
+
result << @rest
|
70
|
+
result.map(&:to_s).join(' ')
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def find_nodes_without_relationship(node, descendant_match: true)
|
76
|
+
return [node] unless @selector
|
77
|
+
|
78
|
+
nodes = []
|
79
|
+
nodes << node if @selector.match?(node)
|
80
|
+
if descendant_match
|
81
|
+
node.recursive_children do |child_node|
|
82
|
+
nodes << child_node if @selector.match?(child_node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
@selector.filter(nodes)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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
|
@@ -0,0 +1,41 @@
|
|
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
|
+
SIMPLE_VALID_OPERATORS
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
@value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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
|
@@ -0,0 +1,23 @@
|
|
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
|
@@ -0,0 +1,37 @@
|
|
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
|
@@ -0,0 +1,51 @@
|
|
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 node_type [String] the node type
|
8
|
+
# @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
|
9
|
+
# @param index [Integer] the index
|
10
|
+
# @param has_expression [Synvert::Core::NodeQuery::Compiler::Expression] the has expression
|
11
|
+
def initialize(node_type: nil, attribute_list: nil, index: nil, has_expression: nil)
|
12
|
+
@node_type = node_type
|
13
|
+
@attribute_list = attribute_list
|
14
|
+
@index = index
|
15
|
+
@has_expression = has_expression
|
16
|
+
end
|
17
|
+
|
18
|
+
# Filter nodes by index.
|
19
|
+
def filter(nodes)
|
20
|
+
return nodes if @index.nil?
|
21
|
+
|
22
|
+
nodes[@index] ? [nodes[@index]] : []
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check if node matches the selector.
|
26
|
+
# @param node [Parser::AST::Node] the node
|
27
|
+
def match?(node, _operator = :==)
|
28
|
+
(!@node_type || (node.is_a?(::Parser::AST::Node) && @node_type.to_sym == node.type)) &&
|
29
|
+
(!@attribute_list || @attribute_list.match?(node)) &&
|
30
|
+
(!@has_expression || @has_expression.match?(node))
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
str = ".#{@node_type}#{@attribute_list}"
|
35
|
+
return str if !@index && !@has_expression
|
36
|
+
|
37
|
+
return "#{str}:has(#{@has_expression})" if @has_expression
|
38
|
+
|
39
|
+
case @index
|
40
|
+
when 0
|
41
|
+
str + ':first-child'
|
42
|
+
when -1
|
43
|
+
str + ':last-child'
|
44
|
+
when (1..)
|
45
|
+
str + ":nth-child(#{@index + 1})"
|
46
|
+
else # ...-1
|
47
|
+
str + ":nth-last-child(#{-@index})"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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
|
+
SIMPLE_VALID_OPERATORS
|
17
|
+
end
|
18
|
+
|
19
|
+
# Get the actual value of a node.
|
20
|
+
# @param node [Parser::AST::Node] the node
|
21
|
+
# @return [String] if node is a Parser::AST::Node, return the node source code, otherwise, return the string value.
|
22
|
+
def actual_value(node)
|
23
|
+
if node.is_a?(::Parser::AST::Node)
|
24
|
+
node.to_source
|
25
|
+
else
|
26
|
+
node.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"\"#{@value}\""
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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
|
@@ -0,0 +1,24 @@
|
|
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 :AttributeList, 'synvert/core/node_query/compiler/attribute_list'
|
12
|
+
autoload :Attribute, 'synvert/core/node_query/compiler/attribute'
|
13
|
+
|
14
|
+
autoload :Array, 'synvert/core/node_query/compiler/array'
|
15
|
+
autoload :Boolean, 'synvert/core/node_query/compiler/boolean'
|
16
|
+
autoload :DynamicAttribute, 'synvert/core/node_query/compiler/dynamic_attribute'
|
17
|
+
autoload :Float, 'synvert/core/node_query/compiler/float'
|
18
|
+
autoload :Identifier, 'synvert/core/node_query/compiler/identifier'
|
19
|
+
autoload :Integer, 'synvert/core/node_query/compiler/integer'
|
20
|
+
autoload :Nil, 'synvert/core/node_query/compiler/nil'
|
21
|
+
autoload :Regexp, 'synvert/core/node_query/compiler/regexp'
|
22
|
+
autoload :String, 'synvert/core/node_query/compiler/string'
|
23
|
+
autoload :Symbol, 'synvert/core/node_query/compiler/symbol'
|
24
|
+
end
|
@@ -0,0 +1,96 @@
|
|
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
|
+
/:first-child/ { [:tINDEX, 0] }
|
31
|
+
/:last-child/ { [:tINDEX, -1] }
|
32
|
+
/:nth-child\(\d+\)/ { [:tINDEX, text.sub(':nth-child(', '').to_i - 1] }
|
33
|
+
/:nth-last-child\(\d+\)/ { [:tINDEX, -text.sub(':nth-last-child(', '').to_i] }
|
34
|
+
/:has/ { [:tHAS, text[1..-1]] }
|
35
|
+
/#{NODE_TYPE}/ { [:tNODE_TYPE, text[1..]] }
|
36
|
+
/>/ { [:tCHILD, text] }
|
37
|
+
/~/ { [:tSUBSEQUENT_SIBLING, text] }
|
38
|
+
/\+/ { [:tNEXT_SIBLING, text] }
|
39
|
+
/#{OPEN_SELECTOR}/ { [:tOPEN_SELECTOR, text] }
|
40
|
+
/#{CLOSE_SELECTOR}/ { [:tCLOSE_SELECTOR, text] }
|
41
|
+
/#{OPEN_ATTRIBUTE}/ { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
|
42
|
+
:KEY /\s+/
|
43
|
+
:KEY /!=/ { @state = :VALUE; [:tNOT_EQUAL, text] }
|
44
|
+
:KEY /=~/ { @state = :VALUE; [:tMATCH, text] }
|
45
|
+
:KEY /!~/ { @state = :VALUE; [:tNOT_MATCH, text] }
|
46
|
+
:KEY />=/ { @state = :VALUE; [:tGREATER_THAN_OR_EQUAL, text] }
|
47
|
+
:KEY /<=/ { @state = :VALUE; [:tLESS_THAN_OR_EQUAL, text] }
|
48
|
+
:KEY />/ { @state = :VALUE; [:tGREATER_THAN, text] }
|
49
|
+
:KEY /</ { @state = :VALUE; [:tLESS_THAN, text] }
|
50
|
+
:KEY /=/ { @state = :VALUE; [:tEQUAL, text] }
|
51
|
+
:KEY /includes/i { @state = :VALUE; [:tINCLUDES, text] }
|
52
|
+
:KEY /not in/i { @state = :VALUE; [:tNOT_IN, text] }
|
53
|
+
:KEY /in/i { @state = :VALUE; [:tIN, text] }
|
54
|
+
:KEY /#{IDENTIFIER}/ { [:tKEY, text] }
|
55
|
+
:VALUE /\s+/
|
56
|
+
:VALUE /#{OPEN_DYNAMIC_ATTRIBUTE}/ { @state = :DYNAMIC_ATTRIBUTE; [:tOPEN_DYNAMIC_ATTRIBUTE, text] }
|
57
|
+
:VALUE /#{OPEN_ARRAY}/ { @state = :ARRAY_VALUE; [:tOPEN_ARRAY, text] }
|
58
|
+
:VALUE /#{CLOSE_ATTRIBUTE}/ { @nested_count -= 1; @state = @nested_count == 0 ? nil : :VALUE; [:tCLOSE_ATTRIBUTE, text] }
|
59
|
+
:VALUE /#{NIL}/ { [:tNIL, nil] }
|
60
|
+
:VALUE /#{TRUE}/ { [:tBOOLEAN, true] }
|
61
|
+
:VALUE /#{FALSE}/ { [:tBOOLEAN, false] }
|
62
|
+
:VALUE /#{SYMBOL}/ { [:tSYMBOL, text[1..-1].to_sym] }
|
63
|
+
:VALUE /#{FLOAT}/ { [:tFLOAT, text.to_f] }
|
64
|
+
:VALUE /#{INTEGER}/ { [:tINTEGER, text.to_i] }
|
65
|
+
:VALUE /#{REGEXP}/ { [:tREGEXP, eval(text)] }
|
66
|
+
:VALUE /#{DOUBLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
|
67
|
+
:VALUE /#{SINGLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
|
68
|
+
:VALUE /#{NODE_TYPE}/ { [:tNODE_TYPE, text[1..]] }
|
69
|
+
:VALUE />/ { [:tCHILD, text] }
|
70
|
+
:VALUE /~/ { [:tSUBSEQUENT_SIBLING, text] }
|
71
|
+
:VALUE /\+/ { [:tNEXT_SIBLING, text] }
|
72
|
+
:VALUE /#{OPEN_ATTRIBUTE}/ { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
|
73
|
+
:VALUE /#{IDENTIFIER_VALUE}/ { [:tIDENTIFIER_VALUE, text] }
|
74
|
+
:DYNAMIC_ATTRIBUTE /#{CLOSE_DYNAMIC_ATTRIBUTE}/ { @state = :VALUE; [:tCLOSE_DYNAMIC_ATTRIBUTE, text] }
|
75
|
+
:DYNAMIC_ATTRIBUTE /#{IDENTIFIER}/ { [:tDYNAMIC_ATTRIBUTE, text] }
|
76
|
+
:ARRAY_VALUE /\s+/
|
77
|
+
:ARRAY_VALUE /,/ { [:tCOMMA, text] }
|
78
|
+
:ARRAY_VALUE /#{CLOSE_ARRAY}/ { @state = :VALUE; [:tCLOSE_ARRAY, text] }
|
79
|
+
:ARRAY_VALUE /#{NIL}/ { [:tNIL, nil] }
|
80
|
+
:ARRAY_VALUE /#{TRUE}/ { [:tBOOLEAN, true] }
|
81
|
+
:ARRAY_VALUE /#{FALSE}/ { [:tBOOLEAN, false] }
|
82
|
+
:ARRAY_VALUE /#{SYMBOL}/ { [:tSYMBOL, text[1..-1].to_sym] }
|
83
|
+
:ARRAY_VALUE /#{FLOAT}/ { [:tFLOAT, text.to_f] }
|
84
|
+
:ARRAY_VALUE /#{INTEGER}/ { [:tINTEGER, text.to_i] }
|
85
|
+
:ARRAY_VALUE /#{REGEXP}/ { [:tREGEXP, eval(text)] }
|
86
|
+
:ARRAY_VALUE /#{DOUBLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
|
87
|
+
:ARRAY_VALUE /#{SINGLE_QUOTE_STRING}/ { [:tSTRING, text[1...-1]] }
|
88
|
+
:ARRAY_VALUE /#{IDENTIFIER_VALUE}/ { [:tIDENTIFIER_VALUE, text] }
|
89
|
+
|
90
|
+
inner
|
91
|
+
def initialize
|
92
|
+
@nested_count = 0
|
93
|
+
end
|
94
|
+
|
95
|
+
def do_parse; end
|
96
|
+
end
|