rubyjedi-oga 1.0.3
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 +7 -0
- data/.yardopts +13 -0
- data/LICENSE +362 -0
- data/README.md +317 -0
- data/doc/css/common.css +77 -0
- data/doc/css_selectors.md +935 -0
- data/doc/manually_creating_documents.md +67 -0
- data/doc/migrating_from_nokogiri.md +169 -0
- data/doc/xml_namespaces.md +63 -0
- data/ext/c/extconf.rb +11 -0
- data/ext/c/lexer.c +2595 -0
- data/ext/c/lexer.h +16 -0
- data/ext/c/lexer.rl +198 -0
- data/ext/c/liboga.c +6 -0
- data/ext/c/liboga.h +11 -0
- data/ext/java/Liboga.java +14 -0
- data/ext/java/org/liboga/xml/Lexer.java +1363 -0
- data/ext/java/org/liboga/xml/Lexer.rl +223 -0
- data/ext/ragel/base_lexer.rl +633 -0
- data/lib/oga.rb +57 -0
- data/lib/oga/blacklist.rb +40 -0
- data/lib/oga/css/lexer.rb +743 -0
- data/lib/oga/css/parser.rb +976 -0
- data/lib/oga/entity_decoder.rb +21 -0
- data/lib/oga/html/entities.rb +2150 -0
- data/lib/oga/html/parser.rb +25 -0
- data/lib/oga/html/sax_parser.rb +18 -0
- data/lib/oga/lru.rb +160 -0
- data/lib/oga/oga.rb +57 -0
- data/lib/oga/version.rb +3 -0
- data/lib/oga/whitelist.rb +20 -0
- data/lib/oga/xml/attribute.rb +136 -0
- data/lib/oga/xml/cdata.rb +17 -0
- data/lib/oga/xml/character_node.rb +37 -0
- data/lib/oga/xml/comment.rb +17 -0
- data/lib/oga/xml/default_namespace.rb +13 -0
- data/lib/oga/xml/doctype.rb +82 -0
- data/lib/oga/xml/document.rb +108 -0
- data/lib/oga/xml/element.rb +428 -0
- data/lib/oga/xml/entities.rb +122 -0
- data/lib/oga/xml/html_void_elements.rb +15 -0
- data/lib/oga/xml/lexer.rb +550 -0
- data/lib/oga/xml/namespace.rb +48 -0
- data/lib/oga/xml/node.rb +219 -0
- data/lib/oga/xml/node_set.rb +333 -0
- data/lib/oga/xml/parser.rb +631 -0
- data/lib/oga/xml/processing_instruction.rb +37 -0
- data/lib/oga/xml/pull_parser.rb +175 -0
- data/lib/oga/xml/querying.rb +56 -0
- data/lib/oga/xml/sax_parser.rb +192 -0
- data/lib/oga/xml/text.rb +66 -0
- data/lib/oga/xml/traversal.rb +50 -0
- data/lib/oga/xml/xml_declaration.rb +65 -0
- data/lib/oga/xpath/evaluator.rb +1798 -0
- data/lib/oga/xpath/lexer.rb +1958 -0
- data/lib/oga/xpath/parser.rb +622 -0
- data/oga.gemspec +45 -0
- metadata +227 -0
@@ -0,0 +1,976 @@
|
|
1
|
+
# This file is automatically generated by ruby-ll. Manually changing this file
|
2
|
+
# is not recommended as any changes will be lost the next time this parser is
|
3
|
+
# re-generated.
|
4
|
+
require 'll/setup'
|
5
|
+
|
6
|
+
module Oga
|
7
|
+
module CSS
|
8
|
+
##
|
9
|
+
# AST parser for CSS expressions.
|
10
|
+
#
|
11
|
+
# This parser does _not_ build a CSS specific AST, instead it directly produces
|
12
|
+
# an XPath AST. This removes the need to transform the AST or generate
|
13
|
+
# corresponding XPath expressions as a String.
|
14
|
+
#
|
15
|
+
# Similar to {Oga::XPath::Parser} this parser only takes String instances as
|
16
|
+
# input.
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
class Parser < LL::Driver
|
21
|
+
CONFIG = LL::DriverConfig.new
|
22
|
+
|
23
|
+
CONFIG.terminals = [
|
24
|
+
:$EOF, # 0
|
25
|
+
:T_IDENT, # 1
|
26
|
+
:T_PIPE, # 2
|
27
|
+
:T_LBRACK, # 3
|
28
|
+
:T_RBRACK, # 4
|
29
|
+
:T_COLON, # 5
|
30
|
+
:T_SPACE, # 6
|
31
|
+
:T_LPAREN, # 7
|
32
|
+
:T_RPAREN, # 8
|
33
|
+
:T_MINUS, # 9
|
34
|
+
:T_EQ, # 10
|
35
|
+
:T_SPACE_IN, # 11
|
36
|
+
:T_STARTS_WITH, # 12
|
37
|
+
:T_ENDS_WITH, # 13
|
38
|
+
:T_IN, # 14
|
39
|
+
:T_HYPHEN_IN, # 15
|
40
|
+
:T_GREATER, # 16
|
41
|
+
:T_TILDE, # 17
|
42
|
+
:T_PLUS, # 18
|
43
|
+
:T_NTH, # 19
|
44
|
+
:T_INT, # 20
|
45
|
+
:T_STRING, # 21
|
46
|
+
:T_ODD, # 22
|
47
|
+
:T_EVEN, # 23
|
48
|
+
:T_DOT, # 24
|
49
|
+
:T_HASH, # 25
|
50
|
+
].freeze
|
51
|
+
|
52
|
+
CONFIG.rules = [
|
53
|
+
[3, 0, 0, 1], # 0
|
54
|
+
[3, 1, 2, 0], # 1
|
55
|
+
[3, 2, 4, 29, 6, 0, 0, 3], # 2
|
56
|
+
[3, 3, 0, 3, 1, 6], # 3
|
57
|
+
[3, 4, 8, 30, 0, 4], # 4
|
58
|
+
[3, 5, 8, 31, 0, 5], # 5
|
59
|
+
[3, 6, 0, 10], # 6
|
60
|
+
[3, 7, 0, 7], # 7
|
61
|
+
[3, 8, 0, 6, 1, 16], # 8
|
62
|
+
[3, 9, 0, 6, 1, 17], # 9
|
63
|
+
[3, 10, 0, 6, 1, 18], # 10
|
64
|
+
[3, 11, 0, 7], # 11
|
65
|
+
[3, 12, 0, 5], # 12
|
66
|
+
[3, 13, 0, 8], # 13
|
67
|
+
[3, 14, 8, 32, 1, 1], # 14
|
68
|
+
[3, 15, 1, 1, 1, 2], # 15
|
69
|
+
[3, 16, 4, 33, 6, 0, 0, 11], # 16
|
70
|
+
[3, 17, 0, 17], # 17
|
71
|
+
[3, 18, 0, 18], # 18
|
72
|
+
[3, 19, 0, 19], # 19
|
73
|
+
[3, 20, 0, 12], # 20
|
74
|
+
[3, 21, 1, 4, 0, 13, 1, 3], # 21
|
75
|
+
[3, 22, 0, 15], # 22
|
76
|
+
[3, 23, 0, 8], # 23
|
77
|
+
[3, 24, 8, 34, 0, 14], # 24
|
78
|
+
[3, 25, 1, 10], # 25
|
79
|
+
[3, 26, 1, 11], # 26
|
80
|
+
[3, 27, 1, 12], # 27
|
81
|
+
[3, 28, 1, 13], # 28
|
82
|
+
[3, 29, 1, 14], # 29
|
83
|
+
[3, 30, 1, 15], # 30
|
84
|
+
[3, 31, 1, 1, 1, 24], # 31
|
85
|
+
[3, 32, 1, 1, 1, 25], # 32
|
86
|
+
[3, 33, 8, 35, 0, 20], # 33
|
87
|
+
[3, 34, 1, 1, 1, 5], # 34
|
88
|
+
[3, 35, 1, 8, 0, 22, 1, 7], # 35
|
89
|
+
[3, 36, 0, 27], # 36
|
90
|
+
[3, 37, 0, 28], # 37
|
91
|
+
[3, 38, 0, 25], # 38
|
92
|
+
[3, 39, 0, 3], # 39
|
93
|
+
[3, 40, 1, 21], # 40
|
94
|
+
[3, 41, 1, 20], # 41
|
95
|
+
[3, 42, 8, 36, 0, 26], # 42
|
96
|
+
[3, 43, 8, 37, 0, 26, 1, 9], # 43
|
97
|
+
[3, 44, 8, 39, 8, 38, 0, 24], # 44
|
98
|
+
[3, 45, 1, 19], # 45
|
99
|
+
[3, 46, 1, 22], # 46
|
100
|
+
[3, 47, 1, 23], # 47
|
101
|
+
[3, 48, 0, 2], # 48
|
102
|
+
[3, 49, 0, 10], # 49
|
103
|
+
[3, 50, 0, 10], # 50
|
104
|
+
[3, 51, 0, 9], # 51
|
105
|
+
[3, 52, 0, 11], # 52
|
106
|
+
[3, 53, 0, 23, 0, 16], # 53
|
107
|
+
[3, 54, 0, 21], # 54
|
108
|
+
[3, 55, 0, 24], # 55
|
109
|
+
[3, 56, 0, 24], # 56
|
110
|
+
[3, 57, 0, 26], # 57
|
111
|
+
[3, 58, 0, 24], # 58
|
112
|
+
].freeze
|
113
|
+
|
114
|
+
CONFIG.table = [
|
115
|
+
[1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0], # 0
|
116
|
+
[-1, 2, -1, 2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 2, -1, -1, -1, -1, -1, 2, 2], # 1
|
117
|
+
[-1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 2
|
118
|
+
[-1, 4, -1, 6, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, 5, -1, -1, -1, -1, -1, 6, 6], # 3
|
119
|
+
[-1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 4
|
120
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1], # 5
|
121
|
+
[-1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 12, 12, -1, -1, -1, -1, -1, -1, -1], # 6
|
122
|
+
[-1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 7
|
123
|
+
[-1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 8
|
124
|
+
[-1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 9
|
125
|
+
[-1, -1, -1, 16, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 16], # 10
|
126
|
+
[-1, -1, -1, 20, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18], # 11
|
127
|
+
[-1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 12
|
128
|
+
[-1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 13
|
129
|
+
[-1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 14
|
130
|
+
[-1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 15
|
131
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 16
|
132
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1], # 17
|
133
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32], # 18
|
134
|
+
[-1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 19
|
135
|
+
[-1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 20
|
136
|
+
[-1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 21
|
137
|
+
[-1, 39, -1, 39, -1, 39, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, 39, 39, 39, 38, 38, -1, 36, 37, 39, 39], # 22
|
138
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1], # 23
|
139
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1], # 24
|
140
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, 44, -1, -1, -1, -1, -1], # 25
|
141
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1], # 26
|
142
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, -1, -1, -1], # 27
|
143
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 47, -1, -1], # 28
|
144
|
+
[-1, -1, -1, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 29
|
145
|
+
[-1, -1, -1, 49, -1, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, 49], # 30
|
146
|
+
[-1, -1, -1, 50, -1, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, 50], # 31
|
147
|
+
[-1, -1, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 32
|
148
|
+
[-1, -1, -1, 52, -1, 52, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, 52], # 33
|
149
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 53, 53, 53, 53, 53, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 34
|
150
|
+
[-1, -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], # 35
|
151
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, -1], # 36
|
152
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 56, -1, -1, -1, -1, -1], # 37
|
153
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 57, -1, -1, -1, -1, -1, -1], # 38
|
154
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, -1, -1, -1, -1], # 39
|
155
|
+
].freeze
|
156
|
+
|
157
|
+
CONFIG.actions = [
|
158
|
+
[:_rule_0, 1], # 0
|
159
|
+
[:_rule_1, 0], # 1
|
160
|
+
[:_rule_2, 2], # 2
|
161
|
+
[:_rule_3, 2], # 3
|
162
|
+
[:_rule_4, 2], # 4
|
163
|
+
[:_rule_5, 2], # 5
|
164
|
+
[:_rule_6, 1], # 6
|
165
|
+
[:_rule_7, 1], # 7
|
166
|
+
[:_rule_8, 2], # 8
|
167
|
+
[:_rule_9, 2], # 9
|
168
|
+
[:_rule_10, 2], # 10
|
169
|
+
[:_rule_11, 1], # 11
|
170
|
+
[:_rule_12, 1], # 12
|
171
|
+
[:_rule_13, 1], # 13
|
172
|
+
[:_rule_14, 2], # 14
|
173
|
+
[:_rule_15, 2], # 15
|
174
|
+
[:_rule_16, 2], # 16
|
175
|
+
[:_rule_17, 1], # 17
|
176
|
+
[:_rule_18, 1], # 18
|
177
|
+
[:_rule_19, 1], # 19
|
178
|
+
[:_rule_20, 1], # 20
|
179
|
+
[:_rule_21, 3], # 21
|
180
|
+
[:_rule_22, 1], # 22
|
181
|
+
[:_rule_23, 1], # 23
|
182
|
+
[:_rule_24, 2], # 24
|
183
|
+
[:_rule_25, 1], # 25
|
184
|
+
[:_rule_26, 1], # 26
|
185
|
+
[:_rule_27, 1], # 27
|
186
|
+
[:_rule_28, 1], # 28
|
187
|
+
[:_rule_29, 1], # 29
|
188
|
+
[:_rule_30, 1], # 30
|
189
|
+
[:_rule_31, 2], # 31
|
190
|
+
[:_rule_32, 2], # 32
|
191
|
+
[:_rule_33, 2], # 33
|
192
|
+
[:_rule_34, 2], # 34
|
193
|
+
[:_rule_35, 3], # 35
|
194
|
+
[:_rule_36, 1], # 36
|
195
|
+
[:_rule_37, 1], # 37
|
196
|
+
[:_rule_38, 1], # 38
|
197
|
+
[:_rule_39, 1], # 39
|
198
|
+
[:_rule_40, 1], # 40
|
199
|
+
[:_rule_41, 1], # 41
|
200
|
+
[:_rule_42, 2], # 42
|
201
|
+
[:_rule_43, 3], # 43
|
202
|
+
[:_rule_44, 3], # 44
|
203
|
+
[:_rule_45, 1], # 45
|
204
|
+
[:_rule_46, 1], # 46
|
205
|
+
[:_rule_47, 1], # 47
|
206
|
+
[:_rule_48, 1], # 48
|
207
|
+
[:_rule_49, 1], # 49
|
208
|
+
[:_rule_50, 1], # 50
|
209
|
+
[:_rule_51, 1], # 51
|
210
|
+
[:_rule_52, 1], # 52
|
211
|
+
[:_rule_53, 2], # 53
|
212
|
+
[:_rule_54, 1], # 54
|
213
|
+
[:_rule_55, 1], # 55
|
214
|
+
[:_rule_56, 1], # 56
|
215
|
+
[:_rule_57, 1], # 57
|
216
|
+
[:_rule_58, 1], # 58
|
217
|
+
].freeze
|
218
|
+
|
219
|
+
##
|
220
|
+
# @return [Oga::LRU]
|
221
|
+
#
|
222
|
+
CACHE = LRU.new
|
223
|
+
|
224
|
+
##
|
225
|
+
# @param [String] data
|
226
|
+
# @return [AST::Node]
|
227
|
+
#
|
228
|
+
def self.parse_with_cache(data)
|
229
|
+
return CACHE.get_or_set(data) { new(data).parse }
|
230
|
+
end
|
231
|
+
|
232
|
+
##
|
233
|
+
# @param [String] data The input to parse.
|
234
|
+
#
|
235
|
+
def initialize(data)
|
236
|
+
@lexer = Lexer.new(data)
|
237
|
+
end
|
238
|
+
|
239
|
+
##
|
240
|
+
# Resets the internal state of the parser.
|
241
|
+
#
|
242
|
+
def reset
|
243
|
+
@current_element = nil
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# @param [Symbol] type
|
248
|
+
# @param [Array] children
|
249
|
+
# @return [AST::Node]
|
250
|
+
#
|
251
|
+
def s(type, *children)
|
252
|
+
return AST::Node.new(type, children)
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# Yields the next token from the lexer.
|
257
|
+
#
|
258
|
+
# @yieldparam [Array]
|
259
|
+
#
|
260
|
+
def each_token
|
261
|
+
@lexer.advance do |*args|
|
262
|
+
yield args
|
263
|
+
end
|
264
|
+
|
265
|
+
yield [-1, -1]
|
266
|
+
end
|
267
|
+
|
268
|
+
##
|
269
|
+
# Returns the node test for the current element.
|
270
|
+
#
|
271
|
+
# @return [AST::Node]
|
272
|
+
#
|
273
|
+
def current_element
|
274
|
+
@current_element ||= s(:test, nil, '*')
|
275
|
+
end
|
276
|
+
|
277
|
+
##
|
278
|
+
# Parses the input and returns the corresponding AST.
|
279
|
+
#
|
280
|
+
# @example
|
281
|
+
# parser = Oga::CSS::Parser.new('foo.bar')
|
282
|
+
# ast = parser.parse
|
283
|
+
#
|
284
|
+
# @return [AST::Node]
|
285
|
+
#
|
286
|
+
def parse
|
287
|
+
reset
|
288
|
+
|
289
|
+
super
|
290
|
+
end
|
291
|
+
|
292
|
+
##
|
293
|
+
# Generates the AST for a node test.
|
294
|
+
#
|
295
|
+
# @param [String] namespace
|
296
|
+
# @param [String] name
|
297
|
+
# @return [AST::Node]
|
298
|
+
#
|
299
|
+
def on_test(namespace, name)
|
300
|
+
@current_element = s(:test, namespace, name)
|
301
|
+
end
|
302
|
+
|
303
|
+
##
|
304
|
+
# @param [String] name
|
305
|
+
# @param [AST::Node] arg
|
306
|
+
# @return [AST::Node]
|
307
|
+
#
|
308
|
+
def on_pseudo_class(name, arg = nil)
|
309
|
+
handler = "on_pseudo_class_#{name.gsub('-', '_')}"
|
310
|
+
|
311
|
+
arg ? send(handler, arg) : send(handler)
|
312
|
+
end
|
313
|
+
|
314
|
+
##
|
315
|
+
# Generates the AST for the `root` pseudo class.
|
316
|
+
#
|
317
|
+
# @return [AST::Node]
|
318
|
+
#
|
319
|
+
def on_pseudo_class_root
|
320
|
+
s(:call, 'not', s(:axis, 'parent', s(:test, nil, '*')))
|
321
|
+
end
|
322
|
+
|
323
|
+
##
|
324
|
+
# Generates the AST for the `nth-child` pseudo class.
|
325
|
+
#
|
326
|
+
# @param [AST::Node] arg
|
327
|
+
# @return [AST::Node]
|
328
|
+
#
|
329
|
+
def on_pseudo_class_nth_child(arg)
|
330
|
+
generate_nth_child('preceding-sibling', arg)
|
331
|
+
end
|
332
|
+
|
333
|
+
##
|
334
|
+
# Generates the AST for the `nth-last-child` pseudo class.
|
335
|
+
#
|
336
|
+
# @param [AST::Node] arg
|
337
|
+
# @return [AST::Node]
|
338
|
+
#
|
339
|
+
def on_pseudo_class_nth_last_child(arg)
|
340
|
+
generate_nth_child('following-sibling', arg)
|
341
|
+
end
|
342
|
+
|
343
|
+
##
|
344
|
+
# Generates the AST for the `nth-of-type` pseudo class.
|
345
|
+
#
|
346
|
+
# @param [AST::Node] arg
|
347
|
+
# @return [AST::Node]
|
348
|
+
#
|
349
|
+
def on_pseudo_class_nth_of_type(arg)
|
350
|
+
generate_nth_child('preceding-sibling', arg, current_element)
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Generates the AST for the `nth-last-of-type` pseudo class.
|
355
|
+
#
|
356
|
+
# @param [AST::Node] arg
|
357
|
+
# @return [AST::Node]
|
358
|
+
#
|
359
|
+
def on_pseudo_class_nth_last_of_type(arg)
|
360
|
+
generate_nth_child('following-sibling', arg, current_element)
|
361
|
+
end
|
362
|
+
|
363
|
+
##
|
364
|
+
# Generates the AST for the `:first-child` selector.
|
365
|
+
#
|
366
|
+
# @return [AST::Node]
|
367
|
+
#
|
368
|
+
def on_pseudo_class_first_child
|
369
|
+
generate_no_siblings('preceding-sibling')
|
370
|
+
end
|
371
|
+
|
372
|
+
##
|
373
|
+
# Generates the AST for the `:last-child` selector.
|
374
|
+
#
|
375
|
+
# @return [AST::Node]
|
376
|
+
#
|
377
|
+
def on_pseudo_class_last_child
|
378
|
+
generate_no_siblings('following-sibling')
|
379
|
+
end
|
380
|
+
|
381
|
+
##
|
382
|
+
# Generates the AST for the `:first-of-type` selector.
|
383
|
+
#
|
384
|
+
# @return [AST::Node]
|
385
|
+
#
|
386
|
+
def on_pseudo_class_first_of_type
|
387
|
+
generate_no_siblings('preceding-sibling', current_element)
|
388
|
+
end
|
389
|
+
|
390
|
+
##
|
391
|
+
# Generates the AST for the `:last-of-type` selector.
|
392
|
+
#
|
393
|
+
# @return [AST::Node]
|
394
|
+
#
|
395
|
+
def on_pseudo_class_last_of_type
|
396
|
+
generate_no_siblings('following-sibling', current_element)
|
397
|
+
end
|
398
|
+
|
399
|
+
##
|
400
|
+
# Generates the AST for the `:only-child` selector.
|
401
|
+
#
|
402
|
+
# @return [AST::Node]
|
403
|
+
#
|
404
|
+
def on_pseudo_class_only_child
|
405
|
+
s(:and, on_pseudo_class_first_child, on_pseudo_class_last_child)
|
406
|
+
end
|
407
|
+
|
408
|
+
##
|
409
|
+
# Generates the AST for the `:only-of-type` selector.
|
410
|
+
#
|
411
|
+
# @return [AST::Node]
|
412
|
+
#
|
413
|
+
def on_pseudo_class_only_of_type
|
414
|
+
s(:and, on_pseudo_class_first_of_type, on_pseudo_class_last_of_type)
|
415
|
+
end
|
416
|
+
|
417
|
+
##
|
418
|
+
# Generates the AST for the `:empty` selector.
|
419
|
+
#
|
420
|
+
# @return [AST::Node]
|
421
|
+
#
|
422
|
+
def on_pseudo_class_empty
|
423
|
+
s(:call, 'not', s(:axis, 'child', s(:type_test, 'node')))
|
424
|
+
end
|
425
|
+
|
426
|
+
##
|
427
|
+
# Generates the AST for the `=` operator.
|
428
|
+
#
|
429
|
+
# @param [AST::Node] attr
|
430
|
+
# @param [AST::Node] value
|
431
|
+
# @return [AST::Node]
|
432
|
+
#
|
433
|
+
def on_op_eq(attr, value)
|
434
|
+
s(:eq, attr, value)
|
435
|
+
end
|
436
|
+
|
437
|
+
##
|
438
|
+
# Generates the AST for the `~=` operator.
|
439
|
+
#
|
440
|
+
# @param [AST::Node] attr
|
441
|
+
# @param [AST::Node] value
|
442
|
+
# @return [AST::Node]
|
443
|
+
#
|
444
|
+
def on_op_space_in(attr, value)
|
445
|
+
s(
|
446
|
+
:call,
|
447
|
+
'contains',
|
448
|
+
s(:call, 'concat', s(:string, ' '), attr, s(:string, ' ')),
|
449
|
+
s(:call, 'concat', s(:string, ' '), value, s(:string, ' '))
|
450
|
+
)
|
451
|
+
end
|
452
|
+
|
453
|
+
##
|
454
|
+
# Generates the AST for the `^=` operator.
|
455
|
+
#
|
456
|
+
# @param [AST::Node] attr
|
457
|
+
# @param [AST::Node] value
|
458
|
+
# @return [AST::Node]
|
459
|
+
#
|
460
|
+
def on_op_starts_with(attr, value)
|
461
|
+
s(:call, 'starts-with', attr, value)
|
462
|
+
end
|
463
|
+
|
464
|
+
##
|
465
|
+
# Generates the AST for the `$=` operator.
|
466
|
+
#
|
467
|
+
# @param [AST::Node] attr
|
468
|
+
# @param [AST::Node] value
|
469
|
+
# @return [AST::Node]
|
470
|
+
#
|
471
|
+
def on_op_ends_with(attr, value)
|
472
|
+
s(
|
473
|
+
:eq,
|
474
|
+
s(
|
475
|
+
:call,
|
476
|
+
'substring',
|
477
|
+
attr,
|
478
|
+
s(
|
479
|
+
:add,
|
480
|
+
s(
|
481
|
+
:sub,
|
482
|
+
s(:call, 'string-length', attr),
|
483
|
+
s(:call, 'string-length', value)
|
484
|
+
),
|
485
|
+
s(:int, 1)
|
486
|
+
),
|
487
|
+
s(:call, 'string-length', value)
|
488
|
+
),
|
489
|
+
value
|
490
|
+
)
|
491
|
+
end
|
492
|
+
|
493
|
+
##
|
494
|
+
# Generates the AST for the `*=` operator.
|
495
|
+
#
|
496
|
+
# @param [AST::Node] attr
|
497
|
+
# @param [AST::Node] value
|
498
|
+
# @return [AST::Node]
|
499
|
+
#
|
500
|
+
def on_op_in(attr, value)
|
501
|
+
s(:call, 'contains', attr, value)
|
502
|
+
end
|
503
|
+
|
504
|
+
##
|
505
|
+
# Generates the AST for the `|=` operator.
|
506
|
+
#
|
507
|
+
# @param [AST::Node] attr
|
508
|
+
# @param [AST::Node] value
|
509
|
+
# @return [AST::Node]
|
510
|
+
#
|
511
|
+
def on_op_hyphen_in(attr, value)
|
512
|
+
s(
|
513
|
+
:or,
|
514
|
+
s(:eq, attr, value),
|
515
|
+
s(
|
516
|
+
:call,
|
517
|
+
'starts-with',
|
518
|
+
attr,
|
519
|
+
s(:call, 'concat', value, s(:string, '-'))
|
520
|
+
)
|
521
|
+
)
|
522
|
+
end
|
523
|
+
|
524
|
+
private
|
525
|
+
|
526
|
+
##
|
527
|
+
# @param [String] count_axis
|
528
|
+
# @param [AST::Node] arg
|
529
|
+
# @param [AST::Node] count_test
|
530
|
+
# @return [AST::Node]
|
531
|
+
#
|
532
|
+
def generate_nth_child(count_axis, arg, count_test = s(:test, nil, '*'))
|
533
|
+
count_call = s(:call, 'count', s(:axis, count_axis, count_test))
|
534
|
+
|
535
|
+
# literal 2, 4, etc
|
536
|
+
if int_node?(arg)
|
537
|
+
node = s(:eq, count_call, s(:int, arg.children[0] - 1))
|
538
|
+
else
|
539
|
+
step, offset = *arg
|
540
|
+
before_count = s(:add, count_call, s(:int, 1))
|
541
|
+
compare = step_comparison(step)
|
542
|
+
|
543
|
+
# 2n+2, 2n-4, etc
|
544
|
+
if offset
|
545
|
+
mod_val = step_modulo_value(step)
|
546
|
+
node = s(
|
547
|
+
:and,
|
548
|
+
s(compare, before_count, offset),
|
549
|
+
s(:eq, s(:mod, s(:sub, before_count, offset), mod_val), s(:int, 0))
|
550
|
+
)
|
551
|
+
|
552
|
+
# 2n, n, -2n
|
553
|
+
else
|
554
|
+
node = s(:eq, s(:mod, before_count, step), s(:int, 0))
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
return node
|
559
|
+
end
|
560
|
+
|
561
|
+
##
|
562
|
+
# @param [String] axis
|
563
|
+
# @param [AST::Node] test
|
564
|
+
# @return [AST::Node]
|
565
|
+
#
|
566
|
+
def generate_no_siblings(axis, test = s(:test, nil, '*'))
|
567
|
+
s(:eq, s(:call, 'count', s(:axis, axis, test)), s(:int, 0))
|
568
|
+
end
|
569
|
+
|
570
|
+
##
|
571
|
+
# @param [AST::Node] node
|
572
|
+
# @return [TrueClass|FalseClass]
|
573
|
+
#
|
574
|
+
def int_node?(node)
|
575
|
+
node.type.equal?(:int)
|
576
|
+
end
|
577
|
+
|
578
|
+
##
|
579
|
+
# @param [AST::Node] node
|
580
|
+
# @return [TrueClass|FalseClass]
|
581
|
+
#
|
582
|
+
def non_positive_number?(node)
|
583
|
+
node.children[0] <= 0
|
584
|
+
end
|
585
|
+
|
586
|
+
##
|
587
|
+
# @param [AST::Node] node
|
588
|
+
# @return [Symbol]
|
589
|
+
#
|
590
|
+
def step_comparison(node)
|
591
|
+
node.children[0] >= 0 ? :gte : :lte
|
592
|
+
end
|
593
|
+
|
594
|
+
##
|
595
|
+
# @param [AST::Node] step
|
596
|
+
# @return [AST::Node]
|
597
|
+
#
|
598
|
+
def step_modulo_value(step)
|
599
|
+
# -2n
|
600
|
+
if step and non_positive_number?(step)
|
601
|
+
mod_val = s(:int, -step.children[0])
|
602
|
+
|
603
|
+
# 2n
|
604
|
+
elsif step
|
605
|
+
mod_val = step
|
606
|
+
|
607
|
+
else
|
608
|
+
mod_val = s(:int, 1)
|
609
|
+
end
|
610
|
+
|
611
|
+
mod_val
|
612
|
+
end
|
613
|
+
|
614
|
+
def _rule_0(val)
|
615
|
+
val[0]
|
616
|
+
end
|
617
|
+
|
618
|
+
def _rule_1(val)
|
619
|
+
nil
|
620
|
+
end
|
621
|
+
|
622
|
+
def _rule_2(val)
|
623
|
+
|
624
|
+
# Single selector
|
625
|
+
if val[1].empty?
|
626
|
+
ret = val[0]
|
627
|
+
|
628
|
+
if ret.is_a?(Array)
|
629
|
+
ret = s(:path, *ret)
|
630
|
+
end
|
631
|
+
|
632
|
+
# Multiple selectors
|
633
|
+
else
|
634
|
+
steps = [val[0]]
|
635
|
+
|
636
|
+
val[1].each do |step|
|
637
|
+
# "+ foo" is broken up into two steps.
|
638
|
+
if step.is_a?(Array)
|
639
|
+
# Using Array#+ or Array#| would require allocating an extra Array
|
640
|
+
step.each { |sub| steps << sub }
|
641
|
+
else
|
642
|
+
steps << step
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
ret = s(:path, *steps)
|
647
|
+
end
|
648
|
+
|
649
|
+
ret
|
650
|
+
|
651
|
+
end
|
652
|
+
|
653
|
+
def _rule_3(val)
|
654
|
+
val[1]
|
655
|
+
end
|
656
|
+
|
657
|
+
def _rule_4(val)
|
658
|
+
|
659
|
+
val[1] ? s(:predicate, val[0], val[1]) : val[0]
|
660
|
+
|
661
|
+
end
|
662
|
+
|
663
|
+
def _rule_5(val)
|
664
|
+
|
665
|
+
val[1] ? s(:predicate, val[0], val[1]) : val[0]
|
666
|
+
|
667
|
+
end
|
668
|
+
|
669
|
+
def _rule_6(val)
|
670
|
+
|
671
|
+
s(:predicate, s(:axis, 'descendant', on_test(nil, '*')), val[0])
|
672
|
+
|
673
|
+
end
|
674
|
+
|
675
|
+
def _rule_7(val)
|
676
|
+
s(:axis, 'descendant', val[0])
|
677
|
+
end
|
678
|
+
|
679
|
+
def _rule_8(val)
|
680
|
+
|
681
|
+
s(:axis, 'child', val[1])
|
682
|
+
|
683
|
+
end
|
684
|
+
|
685
|
+
def _rule_9(val)
|
686
|
+
|
687
|
+
s(:axis, 'following-sibling', val[1])
|
688
|
+
|
689
|
+
end
|
690
|
+
|
691
|
+
def _rule_10(val)
|
692
|
+
|
693
|
+
[
|
694
|
+
s(
|
695
|
+
:predicate,
|
696
|
+
s(:axis, 'following-sibling', on_test(nil, '*')),
|
697
|
+
s(:int, 1)
|
698
|
+
),
|
699
|
+
s(:axis, 'self', val[1])
|
700
|
+
]
|
701
|
+
|
702
|
+
end
|
703
|
+
|
704
|
+
def _rule_11(val)
|
705
|
+
val[0]
|
706
|
+
end
|
707
|
+
|
708
|
+
def _rule_12(val)
|
709
|
+
val[0]
|
710
|
+
end
|
711
|
+
|
712
|
+
def _rule_13(val)
|
713
|
+
on_test(*val[0])
|
714
|
+
end
|
715
|
+
|
716
|
+
def _rule_14(val)
|
717
|
+
val[1] ? [val[0], val[1]] : [nil, val[0]]
|
718
|
+
end
|
719
|
+
|
720
|
+
def _rule_15(val)
|
721
|
+
val[1]
|
722
|
+
end
|
723
|
+
|
724
|
+
def _rule_16(val)
|
725
|
+
|
726
|
+
ret = val[0]
|
727
|
+
|
728
|
+
val[1].each do |pred|
|
729
|
+
ret = s(:and, ret, pred)
|
730
|
+
end
|
731
|
+
|
732
|
+
ret
|
733
|
+
|
734
|
+
end
|
735
|
+
|
736
|
+
def _rule_17(val)
|
737
|
+
val[0]
|
738
|
+
end
|
739
|
+
|
740
|
+
def _rule_18(val)
|
741
|
+
val[0]
|
742
|
+
end
|
743
|
+
|
744
|
+
def _rule_19(val)
|
745
|
+
val[0]
|
746
|
+
end
|
747
|
+
|
748
|
+
def _rule_20(val)
|
749
|
+
val[0]
|
750
|
+
end
|
751
|
+
|
752
|
+
def _rule_21(val)
|
753
|
+
val[1]
|
754
|
+
end
|
755
|
+
|
756
|
+
def _rule_22(val)
|
757
|
+
val[0]
|
758
|
+
end
|
759
|
+
|
760
|
+
def _rule_23(val)
|
761
|
+
s(:axis, 'attribute', on_test(*val[0]))
|
762
|
+
end
|
763
|
+
|
764
|
+
def _rule_24(val)
|
765
|
+
|
766
|
+
op_type = val[1] ? val[1][0] : nil
|
767
|
+
|
768
|
+
case op_type
|
769
|
+
# a="b"
|
770
|
+
when :eq
|
771
|
+
on_op_eq(val[0], val[1][1])
|
772
|
+
|
773
|
+
# a~="b"
|
774
|
+
when :space_in
|
775
|
+
on_op_space_in(val[0], val[1][1])
|
776
|
+
|
777
|
+
# a^="b"
|
778
|
+
when :starts_with
|
779
|
+
on_op_starts_with(val[0], val[1][1])
|
780
|
+
|
781
|
+
# a$="b"
|
782
|
+
when :ends_with
|
783
|
+
on_op_ends_with(val[0], val[1][1])
|
784
|
+
|
785
|
+
# a*="b"
|
786
|
+
when :in
|
787
|
+
on_op_in(val[0], val[1][1])
|
788
|
+
|
789
|
+
# a|="b"
|
790
|
+
when :hyphen_in
|
791
|
+
on_op_hyphen_in(val[0], val[1][1])
|
792
|
+
|
793
|
+
else
|
794
|
+
val[0]
|
795
|
+
end
|
796
|
+
|
797
|
+
end
|
798
|
+
|
799
|
+
def _rule_25(val)
|
800
|
+
:eq
|
801
|
+
end
|
802
|
+
|
803
|
+
def _rule_26(val)
|
804
|
+
:space_in
|
805
|
+
end
|
806
|
+
|
807
|
+
def _rule_27(val)
|
808
|
+
:starts_with
|
809
|
+
end
|
810
|
+
|
811
|
+
def _rule_28(val)
|
812
|
+
:ends_with
|
813
|
+
end
|
814
|
+
|
815
|
+
def _rule_29(val)
|
816
|
+
:in
|
817
|
+
end
|
818
|
+
|
819
|
+
def _rule_30(val)
|
820
|
+
:hyphen_in
|
821
|
+
end
|
822
|
+
|
823
|
+
def _rule_31(val)
|
824
|
+
|
825
|
+
axis = s(:axis, 'attribute', s(:test, nil, 'class'))
|
826
|
+
|
827
|
+
s(
|
828
|
+
:call,
|
829
|
+
'contains',
|
830
|
+
s(:call, 'concat', s(:string, ' '), axis, s(:string, ' ')),
|
831
|
+
s(:string, " #{val[1]} ")
|
832
|
+
)
|
833
|
+
|
834
|
+
end
|
835
|
+
|
836
|
+
def _rule_32(val)
|
837
|
+
|
838
|
+
s(
|
839
|
+
:eq,
|
840
|
+
s(:axis, 'attribute', s(:test, nil, 'id')),
|
841
|
+
s(:string, val[1])
|
842
|
+
)
|
843
|
+
|
844
|
+
end
|
845
|
+
|
846
|
+
def _rule_33(val)
|
847
|
+
on_pseudo_class(val[0], val[1])
|
848
|
+
end
|
849
|
+
|
850
|
+
def _rule_34(val)
|
851
|
+
val[1]
|
852
|
+
end
|
853
|
+
|
854
|
+
def _rule_35(val)
|
855
|
+
val[1]
|
856
|
+
end
|
857
|
+
|
858
|
+
def _rule_36(val)
|
859
|
+
val[0]
|
860
|
+
end
|
861
|
+
|
862
|
+
def _rule_37(val)
|
863
|
+
val[0]
|
864
|
+
end
|
865
|
+
|
866
|
+
def _rule_38(val)
|
867
|
+
val[0]
|
868
|
+
end
|
869
|
+
|
870
|
+
def _rule_39(val)
|
871
|
+
val[0]
|
872
|
+
end
|
873
|
+
|
874
|
+
def _rule_40(val)
|
875
|
+
s(:string, val[0])
|
876
|
+
end
|
877
|
+
|
878
|
+
def _rule_41(val)
|
879
|
+
s(:int, val[0].to_i)
|
880
|
+
end
|
881
|
+
|
882
|
+
def _rule_42(val)
|
883
|
+
|
884
|
+
val[1] ? s(:nth, s(:int, 1), val[1]) : s(:nth, s(:int, 1))
|
885
|
+
|
886
|
+
end
|
887
|
+
|
888
|
+
def _rule_43(val)
|
889
|
+
|
890
|
+
val[2] ? s(:nth, s(:int, -1), val[2]) : s(:nth, s(:int, 1))
|
891
|
+
|
892
|
+
end
|
893
|
+
|
894
|
+
def _rule_44(val)
|
895
|
+
|
896
|
+
# 2n+1
|
897
|
+
if val[1] and val[2]
|
898
|
+
a = val[0]
|
899
|
+
b = val[2]
|
900
|
+
|
901
|
+
# 2n-1 gets turned into 2n+1
|
902
|
+
if b.children[0] < 0
|
903
|
+
b = s(:int, a.children[0] - (b.children[0] % a.children[0]))
|
904
|
+
end
|
905
|
+
|
906
|
+
s(:nth, a, b)
|
907
|
+
|
908
|
+
# 2n
|
909
|
+
elsif val[1]
|
910
|
+
s(:nth, val[0])
|
911
|
+
|
912
|
+
# 2
|
913
|
+
else
|
914
|
+
val[0]
|
915
|
+
end
|
916
|
+
|
917
|
+
end
|
918
|
+
|
919
|
+
def _rule_45(val)
|
920
|
+
:nth
|
921
|
+
end
|
922
|
+
|
923
|
+
def _rule_46(val)
|
924
|
+
s(:nth, s(:int, 2), s(:int, 1))
|
925
|
+
end
|
926
|
+
|
927
|
+
def _rule_47(val)
|
928
|
+
s(:nth, s(:int, 2))
|
929
|
+
end
|
930
|
+
|
931
|
+
def _rule_48(val)
|
932
|
+
val[0]
|
933
|
+
end
|
934
|
+
|
935
|
+
def _rule_49(val)
|
936
|
+
val[0]
|
937
|
+
end
|
938
|
+
|
939
|
+
def _rule_50(val)
|
940
|
+
val[0]
|
941
|
+
end
|
942
|
+
|
943
|
+
def _rule_51(val)
|
944
|
+
val[0]
|
945
|
+
end
|
946
|
+
|
947
|
+
def _rule_52(val)
|
948
|
+
val[0]
|
949
|
+
end
|
950
|
+
|
951
|
+
def _rule_53(val)
|
952
|
+
val
|
953
|
+
end
|
954
|
+
|
955
|
+
def _rule_54(val)
|
956
|
+
val[0]
|
957
|
+
end
|
958
|
+
|
959
|
+
def _rule_55(val)
|
960
|
+
val[0]
|
961
|
+
end
|
962
|
+
|
963
|
+
def _rule_56(val)
|
964
|
+
val[0]
|
965
|
+
end
|
966
|
+
|
967
|
+
def _rule_57(val)
|
968
|
+
val[0]
|
969
|
+
end
|
970
|
+
|
971
|
+
def _rule_58(val)
|
972
|
+
val[0]
|
973
|
+
end
|
974
|
+
end
|
975
|
+
end
|
976
|
+
end
|