Remove (path) usage from the CSS parser

This updates the CSS parser to make it compatible with the XPath AST
changes introduced in commit 365a9e9fa9.
This also, finally, means I can get rid of some of the hacks that were
used for "+ foo" selectors and building (path) nodes.
This commit is contained in:
Yorick Peterse 2015-08-26 19:15:12 +02:00
parent 365a9e9fa9
commit 083d048e63
1 changed files with 57 additions and 59 deletions

View File

@ -27,73 +27,79 @@ css
; ;
selectors selectors
= path selectors_follow* = selector selectors_follow*
{ {
path = val[0] node = val[0]
val[1].each do |chunk| val[1].each do |chunk|
path = s(:pipe, path, chunk) node = s(:pipe, node, chunk)
end end
path node
} }
; ;
selectors_follow selectors_follow
= T_COMMA path { val[1] } = T_COMMA selector { val[1] }
;
path
= selector path_follow*
{
# Single selector
if val[1].empty?
ret = val[0]
if ret.is_a?(Array)
ret = s(:path, *ret)
end
# Multiple selectors
else
steps = [val[0]]
val[1].each do |step|
# "+ foo" is broken up into two steps.
if step.is_a?(Array)
# Using Array#+ or Array#| would require allocating an extra Array
step.each { |sub| steps << sub }
else
steps << step
end
end
ret = s(:path, *steps)
end
ret
}
;
path_follow
= T_SPACE selector { val[1] }
; ;
selector selector
= descendant_or_self predicates? = axis_or_descendant_or_self predicates? selector_follow?
{ {
val[1] ? s(:predicate, val[0], val[1]) : val[0] node = val[0]
pred = val[1]
more = val[2]
if pred
node = s(:predicate, node, pred)
end
if more
node = node.updated(nil, node.children + [more])
end
node
} }
| axis predicates? | predicates selector_follow?
{ {
val[1] ? s(:predicate, val[0], val[1]) : val[0] node = s(:axis, 'descendant', on_test(nil, '*'))
preds = val[0]
more = val[1]
if more
s(:predicate, node, preds, more)
else
s(:predicate, node, preds)
end
} }
| predicates # + foo
#
# This branch is not part of the "axis" rule because we need more fine grained
# control over what to do with any selec
| T_PLUS axis_selector selector_follow?
{ {
s(:predicate, s(:axis, 'descendant', on_test(nil, '*')), val[0]) selector = val[1]
more = val[2]
if more
child = s(:axis, 'self', selector, more)
else
child = s(:axis, 'self', selector)
end
s(
:predicate,
s(:axis, 'following-sibling', on_test(nil, '*')),
s(:int, 1),
child
)
} }
; ;
selector_follow
= T_SPACE selector { val[1] }
;
descendant_or_self descendant_or_self
= node_test { s(:axis, 'descendant', val[0]) } = node_test { s(:axis, 'descendant', val[0]) }
; ;
@ -110,19 +116,11 @@ axis
{ {
s(:axis, 'following-sibling', val[1]) s(:axis, 'following-sibling', val[1])
} }
;
# + foo axis_or_descendant_or_self
| T_PLUS axis_selector = descendant_or_self
{ | axis
[
s(
:predicate,
s(:axis, 'following-sibling', on_test(nil, '*')),
s(:int, 1)
),
s(:axis, 'self', val[1])
]
}
; ;
axis_selector axis_selector