Basic setup for lexing CSS pseudo selectors.
This includes support for the crazy 2n+1 syntax you can use with selectors such as :nth-child(). CSS selectors: doing what XPath already does using an even crazier syntax, because screw you.
This commit is contained in:
parent
ea4a429430
commit
73c5dbe636
|
@ -137,6 +137,9 @@ module Oga
|
|||
dot = '.' %{ add_token(:T_DOT) };
|
||||
lbrack = '[' %{ add_token(:T_LBRACK) };
|
||||
rbrack = ']' %{ add_token(:T_RBRACK) };
|
||||
colon = ':' %{ add_token(:T_COLON) };
|
||||
lparen = '(' %{ add_token(:T_LPAREN) };
|
||||
rparen = ')' %{ add_token(:T_RPAREN) };
|
||||
pipe = '|';
|
||||
|
||||
# Identifiers
|
||||
|
@ -168,8 +171,43 @@ module Oga
|
|||
op_fol_direct = '+';
|
||||
op_fol = '~';
|
||||
|
||||
# Numbers
|
||||
#
|
||||
# CSS selectors only understand integers, floating points are not
|
||||
# supported.
|
||||
|
||||
integer = ('-' | '+')* digit+;
|
||||
|
||||
action emit_integer {
|
||||
value = slice_input(ts, te).to_i
|
||||
|
||||
add_token(:T_INT, value)
|
||||
}
|
||||
|
||||
# Nth numbers
|
||||
#
|
||||
# These numbers are in the form of 2n+1 and are used for
|
||||
# pseudo-selectors such as nth-child(2n+1). The following parts such as
|
||||
# "-1" and "+1" are handled by the `integer` type and the corresponding
|
||||
# `emit_integer` action.
|
||||
|
||||
nth_integer = integer 'n';
|
||||
nth_identifier = '+n' | '-n';
|
||||
|
||||
action emit_nth_integer {
|
||||
value = slice_input(ts, te - 1).to_i
|
||||
|
||||
add_token(:T_INT, value)
|
||||
add_token(:T_NTH, 'n')
|
||||
}
|
||||
|
||||
action emit_nth_identifier {
|
||||
emit(:T_NTH, ts, te)
|
||||
}
|
||||
|
||||
main := |*
|
||||
whitespace | comma | hash | dot | lbrack | rbrack;
|
||||
whitespace | comma | hash | dot | lbrack | rbrack | colon;
|
||||
lparen | rparen;
|
||||
|
||||
# Some of the operators have similar characters (e.g. the "="). As a
|
||||
# result we can't use rules like the following:
|
||||
|
@ -194,7 +232,10 @@ module Oga
|
|||
# this is handled separately.
|
||||
pipe => { add_token(:T_PIPE) };
|
||||
|
||||
identifier => emit_identifier;
|
||||
identifier => emit_identifier;
|
||||
nth_integer => emit_nth_integer;
|
||||
nth_identifier => emit_nth_identifier;
|
||||
integer => emit_integer;
|
||||
|
||||
any;
|
||||
*|;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Oga::CSS::Lexer do
|
||||
context 'integers' do
|
||||
example 'lex an integer' do
|
||||
lex_css('10').should == [[:T_INT, 10]]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Oga::CSS::Lexer do
|
||||
context 'nth numbers' do
|
||||
example 'lex the 2n number' do
|
||||
lex_css('2n').should == [[:T_INT, 2], [:T_NTH, 'n']]
|
||||
end
|
||||
|
||||
example 'lex the 2n+1 number' do
|
||||
lex_css('2n+1').should == [[:T_INT, 2], [:T_NTH, 'n'], [:T_INT, 1]]
|
||||
end
|
||||
|
||||
example 'lex the 2n-1 number' do
|
||||
lex_css('2n-1').should == [[:T_INT, 2], [:T_NTH, 'n'], [:T_INT, -1]]
|
||||
end
|
||||
|
||||
example 'lex the 2n -1 number' do
|
||||
lex_css('2n -1').should == [[:T_INT, 2], [:T_NTH, 'n'], [:T_INT, -1]]
|
||||
end
|
||||
|
||||
example 'lex the -n number' do
|
||||
lex_css('-n').should == [[:T_NTH, '-n']]
|
||||
end
|
||||
|
||||
example 'lex the +n number' do
|
||||
lex_css('+n').should == [[:T_NTH, '+n']]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Oga::CSS::Lexer do
|
||||
context 'pseudo classes' do
|
||||
example 'lex the :root pseudo class' do
|
||||
lex_css(':root').should == [
|
||||
[:T_COLON, nil],
|
||||
[:T_IDENT, 'root']
|
||||
]
|
||||
end
|
||||
|
||||
example 'lex the :nth-child pseudo class' do
|
||||
lex_css(':nth-child(1)').should == [
|
||||
[:T_COLON, nil],
|
||||
[:T_IDENT, 'nth-child'],
|
||||
[:T_LPAREN, nil],
|
||||
[:T_INT, 1],
|
||||
[:T_RPAREN, nil]
|
||||
]
|
||||
end
|
||||
|
||||
example 'lex the :nth-child pseudo class using "odd" as an argument' do
|
||||
lex_css(':nth-child(odd)').should == [
|
||||
[:T_COLON, nil],
|
||||
[:T_IDENT, 'nth-child'],
|
||||
[:T_LPAREN, nil],
|
||||
[:T_IDENT, 'odd'],
|
||||
[:T_RPAREN, nil]
|
||||
]
|
||||
end
|
||||
|
||||
example 'lex the :nth-child pseudo class using "2n+1" as an argument' do
|
||||
lex_css(':nth-child(2n+1)').should == [
|
||||
[:T_COLON, nil],
|
||||
[:T_IDENT, 'nth-child'],
|
||||
[:T_LPAREN, nil],
|
||||
[:T_INT, 2],
|
||||
[:T_NTH, 'n'],
|
||||
[:T_INT, 1],
|
||||
[:T_RPAREN, nil]
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue