Support for parsing CSS operators.
This commit is contained in:
parent
e03cd42735
commit
8fef62fca0
|
@ -147,7 +147,7 @@ module Oga
|
||||||
# Identifiers are used for element and attribute names. Identifiers have
|
# Identifiers are used for element and attribute names. Identifiers have
|
||||||
# to start with a letter.
|
# to start with a letter.
|
||||||
|
|
||||||
identifier = [a-zA-Z*]+ [a-zA-Z\-_0-9]*;
|
identifier = '*' | [a-zA-Z]+ [a-zA-Z\-_0-9]*;
|
||||||
|
|
||||||
action emit_identifier {
|
action emit_identifier {
|
||||||
emit(:T_IDENT, ts, te)
|
emit(:T_IDENT, ts, te)
|
||||||
|
@ -184,6 +184,23 @@ module Oga
|
||||||
add_token(:T_INT, value)
|
add_token(:T_INT, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Strings
|
||||||
|
#
|
||||||
|
# Strings can be single or double quoted. They are mainly used for
|
||||||
|
# attribute values.
|
||||||
|
#
|
||||||
|
dquote = '"';
|
||||||
|
squote = "'";
|
||||||
|
|
||||||
|
string_dquote = (dquote ^dquote* dquote);
|
||||||
|
string_squote = (squote ^squote* squote);
|
||||||
|
|
||||||
|
string = string_dquote | string_squote;
|
||||||
|
|
||||||
|
action emit_string {
|
||||||
|
emit(:T_STRING, ts + 1, te - 1)
|
||||||
|
}
|
||||||
|
|
||||||
# Nth numbers
|
# Nth numbers
|
||||||
#
|
#
|
||||||
# These numbers are in the form of 2n+1 and are used for
|
# These numbers are in the form of 2n+1 and are used for
|
||||||
|
@ -236,6 +253,7 @@ module Oga
|
||||||
nth_integer => emit_nth_integer;
|
nth_integer => emit_nth_integer;
|
||||||
nth_identifier => emit_nth_identifier;
|
nth_identifier => emit_nth_identifier;
|
||||||
integer => emit_integer;
|
integer => emit_integer;
|
||||||
|
string => emit_string;
|
||||||
|
|
||||||
any;
|
any;
|
||||||
*|;
|
*|;
|
||||||
|
|
|
@ -14,6 +14,7 @@ rule
|
||||||
expression
|
expression
|
||||||
: path
|
: path
|
||||||
| node_test
|
| node_test
|
||||||
|
| node_operators
|
||||||
;
|
;
|
||||||
|
|
||||||
path_member
|
path_member
|
||||||
|
@ -46,7 +47,39 @@ rule
|
||||||
;
|
;
|
||||||
|
|
||||||
predicate
|
predicate
|
||||||
: T_LBRACK expression T_RBRACK { val[1] }
|
: T_LBRACK predicate_members T_RBRACK { val[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
predicate_members
|
||||||
|
: expression { val[0] }
|
||||||
|
| operator { val[0] }
|
||||||
|
;
|
||||||
|
|
||||||
|
operator
|
||||||
|
: op_members T_EQ op_members { s(:eq, val[0], val[2]) }
|
||||||
|
| op_members T_SPACE_IN op_members { s(:space_in, val[0], val[2]) }
|
||||||
|
| op_members T_STARTS_WITH op_members { s(:starts_with, val[0], val[2]) }
|
||||||
|
| op_members T_ENDS_WITH op_members { s(:ends_with, val[0], val[2]) }
|
||||||
|
| op_members T_IN op_members { s(:in, val[0], val[2]) }
|
||||||
|
| op_members T_HYPHEN_IN op_members { s(:hyphen_in, val[0],val[2]) }
|
||||||
|
;
|
||||||
|
|
||||||
|
node_operators
|
||||||
|
: node_test T_CHILD node_test { s(:child, val[0], val[2]) }
|
||||||
|
| node_test T_FOLLOWING node_test { s(:following, val[0], val[2]) }
|
||||||
|
| node_test T_FOLLOWING_DIRECT node_test
|
||||||
|
{
|
||||||
|
s(:following_direct, val[0], val[2])
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
op_members
|
||||||
|
: node_test
|
||||||
|
| string
|
||||||
|
;
|
||||||
|
|
||||||
|
string
|
||||||
|
: T_STRING { s(:string, val[0]) }
|
||||||
;
|
;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,10 @@ describe Oga::CSS::Lexer do
|
||||||
lex_css('*=').should == [[:T_IN, nil]]
|
lex_css('*=').should == [[:T_IN, nil]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
example 'lex an identifier followed by the *= operator' do
|
||||||
|
lex_css('foo *=').should == [[:T_IDENT, 'foo'], [:T_IN, nil]]
|
||||||
|
end
|
||||||
|
|
||||||
example 'lex the |= operator' do
|
example 'lex the |= operator' do
|
||||||
lex_css('|=').should == [[:T_HYPHEN_IN, nil]]
|
lex_css('|=').should == [[:T_HYPHEN_IN, nil]]
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Oga::CSS::Lexer do
|
||||||
|
context 'strings' do
|
||||||
|
example 'lex a single quoted string' do
|
||||||
|
lex_css("'foo'").should == [[:T_STRING, 'foo']]
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'lex a double quoted string' do
|
||||||
|
lex_css('"foo"').should == [[:T_STRING, 'foo']]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,83 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Oga::CSS::Parser do
|
||||||
|
context 'operators' do
|
||||||
|
example 'parse the = operator' do
|
||||||
|
parse_css('x[a="b"]').should == s(
|
||||||
|
:test,
|
||||||
|
nil,
|
||||||
|
'x',
|
||||||
|
s(:eq, s(:test, nil, 'a'), s(:string, 'b'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the ~= operator' do
|
||||||
|
parse_css('x[a~="b"]').should == s(
|
||||||
|
:test,
|
||||||
|
nil,
|
||||||
|
'x',
|
||||||
|
s(:space_in, s(:test, nil, 'a'), s(:string, 'b'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the ^= operator' do
|
||||||
|
parse_css('x[a^="b"]').should == s(
|
||||||
|
:test,
|
||||||
|
nil,
|
||||||
|
'x',
|
||||||
|
s(:starts_with, s(:test, nil, 'a'), s(:string, 'b'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the $= operator' do
|
||||||
|
parse_css('x[a$="b"]').should == s(
|
||||||
|
:test,
|
||||||
|
nil,
|
||||||
|
'x',
|
||||||
|
s(:ends_with, s(:test, nil, 'a'), s(:string, 'b'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the *= operator' do
|
||||||
|
parse_css('x[a*="b"]').should == s(
|
||||||
|
:test,
|
||||||
|
nil,
|
||||||
|
'x',
|
||||||
|
s(:in, s(:test, nil, 'a'), s(:string, 'b'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the |= operator' do
|
||||||
|
parse_css('x[a|="b"]').should == s(
|
||||||
|
:test,
|
||||||
|
nil,
|
||||||
|
'x',
|
||||||
|
s(:hyphen_in, s(:test, nil, 'a'), s(:string, 'b'))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the > operator' do
|
||||||
|
parse_css('x > y').should == s(
|
||||||
|
:child,
|
||||||
|
s(:test, nil, 'x'),
|
||||||
|
s(:test, nil, 'y')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the + operator' do
|
||||||
|
parse_css('x + y').should == s(
|
||||||
|
:following_direct,
|
||||||
|
s(:test, nil, 'x'),
|
||||||
|
s(:test, nil, 'y')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'parse the ~ operator' do
|
||||||
|
parse_css('x ~ y').should == s(
|
||||||
|
:following,
|
||||||
|
s(:test, nil, 'x'),
|
||||||
|
s(:test, nil, 'y')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue