Reworked CSS parser rules.
This includes better rules for parsing separate path members, pseudo class arguments and some changes to remove all remaining parsing conflicts.
This commit is contained in:
parent
b40c0243ce
commit
6792127600
|
@ -3,30 +3,44 @@
|
||||||
#
|
#
|
||||||
class Oga::CSS::Parser
|
class Oga::CSS::Parser
|
||||||
|
|
||||||
|
token T_IDENT T_PIPE T_LBRACK T_RBRACK T_COLON T_SPACE T_LPAREN T_RPAREN T_MINUS
|
||||||
|
token T_EQ T_SPACE_IN T_STARTS_WITH T_ENDS_WITH T_IN T_HYPHEN_IN
|
||||||
|
token T_CHILD T_FOLLOWING T_FOLLOWING_DIRECT
|
||||||
|
token T_NTH T_INT T_STRING T_ODD T_EVEN
|
||||||
|
|
||||||
options no_result_var
|
options no_result_var
|
||||||
|
|
||||||
|
prechigh
|
||||||
|
left T_COLON
|
||||||
|
left T_CHILD T_FOLLOWING T_FOLLOWING_DIRECT
|
||||||
|
preclow
|
||||||
|
|
||||||
rule
|
rule
|
||||||
css
|
css
|
||||||
: path { val[0] }
|
: expression { val[0] }
|
||||||
| /* none */ { nil }
|
| /* none */ { nil }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: path
|
||||||
|
| path_member
|
||||||
|
;
|
||||||
|
|
||||||
|
path
|
||||||
|
: path_members { s(:path, *val[0]) }
|
||||||
|
;
|
||||||
|
|
||||||
|
path_members
|
||||||
|
: path_member T_SPACE path_member { [val[0], val[2]] }
|
||||||
|
| path_member T_SPACE path_members { [val[0], *val[2]] }
|
||||||
|
;
|
||||||
|
|
||||||
path_member
|
path_member
|
||||||
: node_test
|
: node_test
|
||||||
| axis
|
| axis
|
||||||
| pseudo_class
|
| pseudo_class
|
||||||
;
|
;
|
||||||
|
|
||||||
path_members
|
|
||||||
: path_member path_member { [val[0], val[1]] }
|
|
||||||
| path_member path_members { [val[0], *val[1]] }
|
|
||||||
;
|
|
||||||
|
|
||||||
path
|
|
||||||
: path_members { s(:path, *val[0]) }
|
|
||||||
| path_member
|
|
||||||
;
|
|
||||||
|
|
||||||
node_test
|
node_test
|
||||||
: node_name { s(:test, *val[0]) }
|
: node_name { s(:test, *val[0]) }
|
||||||
| node_name predicate { s(:test, *val[0], val[1]) }
|
| node_name predicate { s(:test, *val[0], val[1]) }
|
||||||
|
@ -68,19 +82,19 @@ rule
|
||||||
|
|
||||||
axis
|
axis
|
||||||
# x > y
|
# x > y
|
||||||
: node_test T_CHILD node_test
|
: path_member T_CHILD path_member
|
||||||
{
|
{
|
||||||
s(:axis, 'child', val[0], val[2])
|
s(:axis, 'child', val[0], val[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
# x + y
|
# x + y
|
||||||
| node_test T_FOLLOWING node_test
|
| path_member T_FOLLOWING path_member
|
||||||
{
|
{
|
||||||
s(:axis, 'following', val[0], val[2])
|
s(:axis, 'following', val[0], val[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
# x ~ y
|
# x ~ y
|
||||||
| node_test T_FOLLOWING_DIRECT node_test
|
| path_member T_FOLLOWING_DIRECT path_member
|
||||||
{
|
{
|
||||||
s(:axis, 'following-direct', val[0], val[2])
|
s(:axis, 'following-direct', val[0], val[2])
|
||||||
}
|
}
|
||||||
|
@ -88,20 +102,15 @@ rule
|
||||||
|
|
||||||
pseudo_class
|
pseudo_class
|
||||||
# x:root
|
# x:root
|
||||||
: node_test T_COLON T_IDENT { s(:pseudo, val[2], val[0]) }
|
: path_member T_COLON T_IDENT { s(:pseudo, val[2], val[0]) }
|
||||||
|
|
||||||
# x:nth-child(2)
|
# x:nth-child(2)
|
||||||
| node_test T_COLON T_IDENT T_LPAREN pseudo_args T_RPAREN
|
| path_member T_COLON T_IDENT T_LPAREN pseudo_arg T_RPAREN
|
||||||
{
|
{
|
||||||
s(:pseudo, val[2], val[0], *val[4])
|
s(:pseudo, val[2], val[0], val[4])
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
pseudo_args
|
|
||||||
: pseudo_args pseudo_arg { val[0] << val[1] }
|
|
||||||
| pseudo_arg { val }
|
|
||||||
;
|
|
||||||
|
|
||||||
pseudo_arg
|
pseudo_arg
|
||||||
: integer
|
: integer
|
||||||
| odd
|
| odd
|
||||||
|
@ -129,8 +138,8 @@ rule
|
||||||
;
|
;
|
||||||
|
|
||||||
integer
|
integer
|
||||||
: T_INT { s(:int, val[0].to_i) }
|
: T_INT { s(:int, val[0].to_i) }
|
||||||
;
|
;
|
||||||
end
|
end
|
||||||
|
|
||||||
---- inner
|
---- inner
|
||||||
|
|
|
@ -11,6 +11,15 @@ describe Oga::CSS::Parser do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
example 'parse the > axis called on another > axis' do
|
||||||
|
parse_css('a > b > c').should == s(
|
||||||
|
:axis,
|
||||||
|
'child',
|
||||||
|
s(:axis, 'child', s(:test, nil, 'a'), s(:test, nil, 'b')),
|
||||||
|
s(:test, nil, 'c')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
example 'parse the + axis' do
|
example 'parse the + axis' do
|
||||||
parse_css('x + y').should == s(
|
parse_css('x + y').should == s(
|
||||||
:axis,
|
:axis,
|
||||||
|
@ -20,6 +29,15 @@ describe Oga::CSS::Parser do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
example 'parse the + axis called on another + axis' do
|
||||||
|
parse_css('a + b + c').should == s(
|
||||||
|
:axis,
|
||||||
|
'following-direct',
|
||||||
|
s(:axis, 'following-direct', s(:test, nil, 'a'), s(:test, nil, 'b')),
|
||||||
|
s(:test, nil, 'c')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
example 'parse the ~ axis' do
|
example 'parse the ~ axis' do
|
||||||
parse_css('x ~ y').should == s(
|
parse_css('x ~ y').should == s(
|
||||||
:axis,
|
:axis,
|
||||||
|
@ -36,5 +54,32 @@ describe Oga::CSS::Parser do
|
||||||
s(:test, nil, 'z')
|
s(:test, nil, 'z')
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
example 'parse the ~ axis called on another ~ axis' do
|
||||||
|
parse_css('a ~ b ~ c').should == s(
|
||||||
|
:axis,
|
||||||
|
'following',
|
||||||
|
s(:axis, 'following', s(:test, nil, 'a'), s(:test, nil, 'b')),
|
||||||
|
s(:test, nil, 'c')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse a pseudo class followed by the ~ axis' do
|
||||||
|
parse_css('x:root ~ a').should == s(
|
||||||
|
:axis,
|
||||||
|
'following',
|
||||||
|
s(:pseudo, 'root', s(:test, nil, 'x')),
|
||||||
|
s(:test, nil, 'a')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the ~ axis followed by a pseudo class' do
|
||||||
|
parse_css('a ~ x:root').should == s(
|
||||||
|
:axis,
|
||||||
|
'following',
|
||||||
|
s(:test, nil, 'a'),
|
||||||
|
s(:pseudo, 'root', s(:test, nil, 'x'))
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -86,5 +86,13 @@ describe Oga::CSS::Parser do
|
||||||
s(:nth, s(:int, -2), s(:int, -1))
|
s(:nth, s(:int, -2), s(:int, -1))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
example 'parse two pseudo selectors' do
|
||||||
|
parse_css('x:focus:hover').should == s(
|
||||||
|
:pseudo,
|
||||||
|
'hover',
|
||||||
|
s(:pseudo, 'focus', s(:test, nil, 'x'))
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue