@@ -59,6 +59,7 @@ import org.w3c.css.util.InvalidParamException;
59
59
import org.w3c.css.util.Util;
60
60
import org.w3c.css.util.WarningParamException;
61
61
import org.w3c.css.values.CssAngle;
62
+ import org.w3c.css.values.CssANPlusB;
62
63
import org.w3c.css.values.CssAttr;
63
64
import org.w3c.css.values.CssBracket;
64
65
import org.w3c.css.values.CssCalc;
@@ -671,6 +672,7 @@ TOKEN [IGNORE_CASE] :
671
672
| < TIME : <NUM> ( "ms" | "s" ) >
672
673
| < FREQ : <NUM> ( "Hz" | "kHz" ) >
673
674
| < RESOLUTION : <NUM> ( "dpi" | "dpcm" | "dppx" | "x") >
675
+ | < AN : <NUM> "n" >
674
676
| < DIMEN_9 : <NUM> <NMSTART> ( <NMCHAR> )* "\\9" >
675
677
| < DIMEN : <NUM> <NMSTART> ( <NMCHAR> )* >
676
678
| < PERCENTAGE : <NUM> "%" >
@@ -763,21 +765,25 @@ TOKEN [IGNORE_CASE] :
763
765
<DEFAULT>
764
766
TOKEN [IGNORE_CASE] :
765
767
{
766
- < FUNCTIONLANG : "lang(" >
767
- | <FUNCTIONDIR : "dir(" >
768
- | <FUNCTIONIS : "is(" >
769
- | <FUNCTIONWHERE : "where(" >
770
- | <FUNCTIONHAS : "has(" >
771
- | <FUNCTIONSLOTTED : "slotted(" >
772
- | <FUNCTIONHOST : "host(" >
773
- | <FUNCTIONHOSTCONTEXT : "host-context(" >
774
- | <FUNCTIONNOT : "not(" >
775
- | <FUNCTIONCALC : "calc(" | "-moz-calc(" | "-webkit-calc(" >
776
- | <FUNCTIONMIN : "min(" >
777
- | <FUNCTIONMAX : "max(" >
778
- | <FUNCTIONCLAMP : "clamp(" >
779
- | <FUNCTIONATTR : "attr(" >
780
- | <FUNCTIONVAR : "var(" >
768
+ < FUNCTIONLANG : "lang(" >
769
+ | <FUNCTIONDIR : "dir(" >
770
+ | <FUNCTIONIS : "is(" >
771
+ | <FUNCTIONWHERE : "where(" >
772
+ | <FUNCTIONHAS : "has(" >
773
+ | <FUNCTIONSLOTTED : "slotted(" >
774
+ | <FUNCTIONHOST : "host(" >
775
+ | <FUNCTIONHOSTCONTEXT : "host-context(" >
776
+ | <FUNCTIONNTHCHILD : "nth-child(" >
777
+ | <FUNCTIONNTHLASTCHILD : "nth-last-child(" >
778
+ | <FUNCTIONNTHOFTYPE : "nth-of-type(" >
779
+ | <FUNCTIONNTHLASTOFTYPE : "nth-last-of-type(" >
780
+ | <FUNCTIONNOT : "not(" >
781
+ | <FUNCTIONCALC : "calc(" | "-moz-calc(" | "-webkit-calc(" >
782
+ | <FUNCTIONMIN : "min(" >
783
+ | <FUNCTIONMAX : "max(" >
784
+ | <FUNCTIONCLAMP : "clamp(" >
785
+ | <FUNCTIONATTR : "attr(" >
786
+ | <FUNCTIONVAR : "var(" >
781
787
}
782
788
783
789
<DEFAULT>
@@ -1929,6 +1935,37 @@ char unaryOperator() :
1929
1935
| <PLUS> { return '+'; }
1930
1936
}
1931
1937
1938
+ CssANPlusB anplusb() :
1939
+ {
1940
+ Token n = null;
1941
+ Token b = null;
1942
+ char op = ' ';
1943
+ char pb = ' ';
1944
+ CssANPlusB anpb = new CssANPlusB();
1945
+ }
1946
+ {
1947
+ // odd/even/n-2/-n-3 ...
1948
+ ( n=ident() ( LOOKAHEAD(2) ( <S> )* ( ( pb=unaryOperator() ( <S> )* )? b=<NUMBER> ) )? ) {
1949
+ anpb.set(n.image, pb, ((b != null) ? b.image : null), "An+B", ac);
1950
+ return anpb;
1951
+ }
1952
+ // +/-num (so no N)
1953
+ | LOOKAHEAD(2) ( ( op=unaryOperator() )? b=<NUMBER> ) {
1954
+ anpb.set(""+op+b.image, ac);
1955
+ return anpb;
1956
+ }
1957
+ // generic aN+b including aN and N+b where N is mandatory
1958
+ | LOOKAHEAD(2) ( ( op=unaryOperator() )? n=<AN> ( LOOKAHEAD(2) ( <S> )* ( pb=unaryOperator() ( <S> )* )? ( b=<NUMBER> ) )? ) {
1959
+ anpb.set(op, n.image, pb, b.image, "An+B", ac);
1960
+ return anpb;
1961
+ }
1962
+ // DIMEN may match 2n- and possibly another number after
1963
+ | ( ( op=unaryOperator() )? n=<DIMEN> ( LOOKAHEAD(2) ( <S> )* b=<NUMBER> )? ) {
1964
+ anpb.set(op, n.image, ((b != null) ? b.image : null), "An+B", ac);
1965
+ return anpb;
1966
+ }
1967
+ }
1968
+
1932
1969
/**
1933
1970
* @exception ParseException exception during the parse
1934
1971
*/
@@ -2251,7 +2288,7 @@ CssSelectors complex_selector(CssSelectors sel) :
2251
2288
{
2252
2289
try {
2253
2290
current=compound_selector(sel)
2254
- ( ( comb=combinator() {
2291
+ ( LOOKAHEAD(2) ( comb=combinator() {
2255
2292
if ((ac.getCssProfile() == CssProfile.MOBILE) ||
2256
2293
getAtRule().toString().equals("@media atsc-tv") ||
2257
2294
(ac.getCssVersion() == CssVersion.CSS1)) {
@@ -2669,13 +2706,17 @@ void pseudo(CssSelectors s) :
2669
2706
* @exception ParseException exception during the parse
2670
2707
*/
2671
2708
void pseudo_class_selector(CssSelectors s) :
2672
- {Token n;
2709
+ {
2710
+ Token n;
2711
+ Token id = null;
2673
2712
Token language = null;
2674
2713
CssExpression param = null;
2675
2714
ArrayList<CssSelectors> selector_list = null;
2676
2715
CssSelectors sel = null;
2677
2716
String error_str = null;
2717
+ String prefix = null;
2678
2718
CssExpression exp = new CssExpression();
2719
+ CssANPlusB anpb = null;
2679
2720
}
2680
2721
{
2681
2722
<COLON> ( ( n=ident()
@@ -2699,7 +2740,7 @@ CssExpression exp = new CssExpression();
2699
2740
getBeginColumn(), getEndLine(), getEndColumn(), e));
2700
2741
}
2701
2742
}
2702
- | ( ( n=<FUNCTIONIS> | n=<FUNCTIONNOT> ) ( <S> )* selector_list=selector_list() ) {
2743
+ | ( ( n=<FUNCTIONIS> | n=<FUNCTIONNOT> ) ( <S> )* selector_list=selector_list() ( <S> )* ) {
2703
2744
try {
2704
2745
s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(), selector_list);
2705
2746
} catch(InvalidParamException e) {
@@ -2708,7 +2749,7 @@ CssExpression exp = new CssExpression();
2708
2749
getBeginColumn(), getEndLine(), getEndColumn(), e));
2709
2750
}
2710
2751
} // we must be more forgiving for :where()
2711
- | ( n=<FUNCTIONWHERE> ( <S> )* try { selector_list=selector_list() } catch (ParseException ignored) {
2752
+ | ( n=<FUNCTIONWHERE> ( <S> )* try { selector_list=selector_list() ( <S> )* } catch (ParseException ignored) {
2712
2753
s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(),
2713
2754
skip_to_matching_paren());
2714
2755
}
@@ -2722,7 +2763,7 @@ CssExpression exp = new CssExpression();
2722
2763
getBeginColumn(), getEndLine(), getEndColumn(), e));
2723
2764
}
2724
2765
}
2725
- | ( n=<FUNCTIONHAS> selector_list=relative_selector_list() ) {
2766
+ | ( n=<FUNCTIONHAS> selector_list=relative_selector_list() ( <S> )* ) {
2726
2767
try {
2727
2768
s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(), selector_list);
2728
2769
} catch(InvalidParamException e) {
@@ -2742,6 +2783,20 @@ CssExpression exp = new CssExpression();
2742
2783
getBeginColumn(), getEndLine(), getEndColumn(), e));
2743
2784
}
2744
2785
}
2786
+ | ( ( n=<FUNCTIONNTHCHILD> | n=<FUNCTIONNTHLASTCHILD> | n=<FUNCTIONNTHOFTYPE> | n=<FUNCTIONNTHLASTOFTYPE> ) ( <S> )*
2787
+ ( ( anpb=anplusb() ( <S> )* ( id=ident() ( <S> )* selector_list=selector_list() ( <S> )* )? ) | error_str=skip_to_matching_paren() ) ) {
2788
+ try {
2789
+ exp.addValue(anpb);
2790
+ if (id != null) {
2791
+ setValue(new CssIdent(), exp, ' ', id, IDENT);
2792
+ }
2793
+ s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(), exp, selector_list);
2794
+ } catch(InvalidParamException e) {
2795
+ removeThisRule();
2796
+ ac.getFrame().addError(new CssError(getSourceFile(), getBeginLine(),
2797
+ getBeginColumn(), getEndLine(), getEndColumn(), e));
2798
+ }
2799
+ }
2745
2800
| ( n=<FUNCTION> ( <S> )* param=expression() ) {
2746
2801
try {
2747
2802
s.setPseudoFun(ac, convertStringIndex(n.image, 0, n.image.length() -1, false).toLowerCase(),
@@ -3795,6 +3850,10 @@ String skip_to_matching_paren() {
3795
3850
case FUNCTIONHOST:
3796
3851
case FUNCTIONHOSTCONTEXT:
3797
3852
case FUNCTIONSLOTTED:
3853
+ case FUNCTIONNTHCHILD:
3854
+ case FUNCTIONNTHLASTCHILD:
3855
+ case FUNCTIONNTHOFTYPE:
3856
+ case FUNCTIONNTHLASTOFTYPE:
3798
3857
case FUNCTIONNOT:
3799
3858
case FUNCTIONCALC:
3800
3859
case FUNCTIONMIN:
0 commit comments