Skip to content

Commit bc010c9

Browse files
committed
Improve CSS comment and white-space parsing
Renamed `spaces_and_comments` to `css_whitespace` and added `css_comments` to complete the prelexer. `css_whitespace` matches white-space and line comments `css_comments` additionally matches css block comments
1 parent dea27e5 commit bc010c9

File tree

5 files changed

+66
-50
lines changed

5 files changed

+66
-50
lines changed

parser.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ namespace Sass {
147147
lex< one_plus< exactly<';'> > >();
148148
}
149149
else {
150-
lex< optional_spaces_and_comments >();
150+
lex< css_whitespace >();
151151
if (position >= end) break;
152152
error("invalid top-level expression", pstate);
153153
}
@@ -477,7 +477,7 @@ namespace Sass {
477477
{
478478
bool reloop = true;
479479
To_String to_string(&ctx);
480-
lex< optional_spaces_and_comments >();
480+
lex< css_whitespace >();
481481
Selector_List* group = new (ctx.mem) Selector_List(pstate);
482482
group->media_block(last_media_block);
483483
group->last_block(block_stack.back());
@@ -508,10 +508,10 @@ namespace Sass {
508508
}
509509
if (peek_newline()) ref_wrap->has_line_break(true);
510510
}
511-
while (peek< sequence< optional_spaces_and_comments, exactly<','> > >())
511+
while (peek< sequence< optional_css_whitespace, optional < block_comment >, exactly<','> > >())
512512
{
513513
// consume everything up and including the comma speparator
514-
reloop = lex< sequence< optional_spaces_and_comments, exactly<','> > >() != 0;
514+
reloop = lex< sequence< optional_css_comments, exactly<','> > >() != 0;
515515
// remember line break (also between some commas)
516516
if (peek_newline()) comb->has_line_feed(true);
517517
if (comb->tail() && peek_newline()) comb->tail()->has_line_feed(true);
@@ -529,7 +529,6 @@ namespace Sass {
529529

530530
Complex_Selector* Parser::parse_selector_combination()
531531
{
532-
// lex< optional_spaces_and_comments >();
533532
Position sel_source_position(-1);
534533
Compound_Selector* lhs;
535534
if (peek< exactly<'+'> >() ||
@@ -685,7 +684,7 @@ namespace Sass {
685684
else if (peek< sequence< optional<sign>,
686685
optional<digits>,
687686
exactly<'n'>,
688-
optional_spaces_and_comments,
687+
optional_css_whitespace,
689688
exactly<')'> > >()) {
690689
lex< sequence< optional<sign>,
691690
optional<digits>,
@@ -695,7 +694,7 @@ namespace Sass {
695694
else if (lex< sequence< optional<sign>, digits > >()) {
696695
expr = new (ctx.mem) String_Quoted(p, lexed);
697696
}
698-
else if (peek< sequence< identifier, optional_spaces_and_comments, exactly<')'> > >()) {
697+
else if (peek< sequence< identifier, optional_css_whitespace, exactly<')'> > >()) {
699698
lex< identifier >();
700699
expr = new (ctx.mem) String_Quoted(p, lexed);
701700
}
@@ -1227,16 +1226,16 @@ namespace Sass {
12271226
else if (peek< functional >() && !peek< uri_prefix >()) {
12281227
return parse_function_call();
12291228
}
1230-
else if (lex< sequence< exactly<'+'>, optional_spaces_and_comments, negate< number > > >()) {
1229+
else if (lex< sequence< exactly<'+'>, optional_css_whitespace, negate< number > > >()) {
12311230
return new (ctx.mem) Unary_Expression(pstate, Unary_Expression::PLUS, parse_factor());
12321231
}
1233-
else if (lex< sequence< exactly<'-'>, optional_spaces_and_comments, negate< number> > >()) {
1232+
else if (lex< sequence< exactly<'-'>, optional_css_whitespace, negate< number> > >()) {
12341233
return new (ctx.mem) Unary_Expression(pstate, Unary_Expression::MINUS, parse_factor());
12351234
}
1236-
else if (lex< sequence< not_op, spaces_and_comments > >()) {
1235+
else if (lex< sequence< not_op, css_whitespace > >()) {
12371236
return new (ctx.mem) Unary_Expression(pstate, Unary_Expression::NOT, parse_factor());
12381237
}
1239-
else if (peek < sequence < one_plus < alternatives < spaces_and_comments, exactly<'-'>, exactly<'+'> > >, number > >()) {
1238+
else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
12401239
if (parse_number_prefix()) return parse_value(); // prefix is positive
12411240
return new (ctx.mem) Unary_Expression(pstate, Unary_Expression::MINUS, parse_value());
12421241
}
@@ -1671,7 +1670,7 @@ namespace Sass {
16711670
if (!lex< variable >()) error("@each directive requires an iteration variable", pstate);
16721671
vector<string> vars;
16731672
vars.push_back(Util::normalize_underscores(lexed));
1674-
while (peek< exactly<','> >() && lex< exactly<','> >()) {
1673+
while (lex< exactly<','> >()) {
16751674
if (!lex< variable >()) error("@each directive requires an iteration variable", pstate);
16761675
vars.push_back(Util::normalize_underscores(lexed));
16771676
}
@@ -1977,7 +1976,7 @@ namespace Sass {
19771976
(q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
19781977
(q = peek< percentage >(p)) ||
19791978
(q = peek< dimension >(p)) ||
1980-
(q = peek< quoted_string >(p)) ||
1979+
(q = peek< quoted_string >(p)) ||
19811980
(q = peek< exactly<'*'> >(p)) ||
19821981
(q = peek< exactly<'('> >(p)) ||
19831982
(q = peek< exactly<')'> >(p)) ||
@@ -1989,6 +1988,7 @@ namespace Sass {
19891988
(q = peek< exactly<','> >(p)) ||
19901989
(saw_stuff && (q = peek< exactly<'-'> >(p))) ||
19911990
(q = peek< binomial >(p)) ||
1991+
(q = peek< block_comment >(p)) ||
19921992
(q = peek< sequence< optional<sign>,
19931993
optional<digits>,
19941994
exactly<'n'> > >(p)) ||
@@ -2036,7 +2036,7 @@ namespace Sass {
20362036
(q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
20372037
(q = peek< percentage >(p)) ||
20382038
(q = peek< dimension >(p)) ||
2039-
(q = peek< quoted_string >(p)) ||
2039+
(q = peek< quoted_string >(p)) ||
20402040
(q = peek< exactly<'*'> >(p)) ||
20412041
(q = peek< exactly<'('> >(p)) ||
20422042
(q = peek< exactly<')'> >(p)) ||
@@ -2048,6 +2048,7 @@ namespace Sass {
20482048
(q = peek< exactly<','> >(p)) ||
20492049
(saw_stuff && (q = peek< exactly<'-'> >(p))) ||
20502050
(q = peek< binomial >(p)) ||
2051+
(q = peek< block_comment >(p)) ||
20512052
(q = peek< sequence< optional<sign>,
20522053
optional<digits>,
20532054
exactly<'n'> > >(p)) ||

parser.hpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ namespace Sass {
9999
it_before_token = position;
100100
}
101101
else {
102-
it_before_token = optional_spaces_and_comments(start);
102+
it_before_token = optional_css_whitespace(start);
103103
}
104104
const char* it_after_token = mx(it_before_token);
105105
if (it_after_token) {
@@ -145,10 +145,11 @@ namespace Sass {
145145
}
146146
}
147147

148-
else if (mx == optional_spaces_and_comments) {
149-
it_before_token = position;
150-
}
151-
else if (mx == spaces_and_comments) {
148+
else if (mx == css_comments ||
149+
mx == css_whitespace ||
150+
mx == optional_css_comments ||
151+
mx == optional_css_whitespace
152+
) {
152153
it_before_token = position;
153154
}
154155

@@ -158,7 +159,7 @@ namespace Sass {
158159
}
159160
else {
160161
// most can be preceded by spaces and comments
161-
it_before_token = optional_spaces_and_comments(position);
162+
it_before_token = optional_css_whitespace(position);
162163
}
163164

164165
// now call matcher to get position after token
@@ -196,7 +197,7 @@ namespace Sass {
196197
after_token = after_token + size;
197198

198199
// create parsed token string (public member)
199-
lexed = Token(wspace_start, it_before_token, it_after_token, optional_spaces_and_comments(it_after_token) ? optional_spaces_and_comments(it_after_token) : it_after_token, before_token);
200+
lexed = Token(wspace_start, it_before_token, it_after_token, optional_css_whitespace(it_after_token) ? optional_css_whitespace(it_after_token) : it_after_token, before_token);
200201
Position pos(before_token.file, before_token.line, before_token.column);
201202
pstate = ParserState(path, lexed, pos, size);
202203

prelexer.cpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,24 @@ namespace Sass {
9898

9999
// Whitespace handling.
100100
const char* optional_spaces(const char* src) { return optional<spaces>(src); }
101-
// const char* optional_comment(const char* src) { return optional<comment>(src); }
102-
const char* optional_spaces_and_comments(const char* src) {
101+
const char* no_spaces(const char* src) { return negate< spaces >(src); }
102+
103+
// Match zero plus white-space or line_comments
104+
const char* optional_css_whitespace(const char* src) {
103105
return zero_plus< alternatives<spaces, line_comment> >(src);
104106
}
105-
const char* spaces_and_comments(const char* src) {
107+
const char* css_whitespace(const char* src) {
106108
return one_plus< alternatives<spaces, line_comment> >(src);
107109
}
108-
const char* no_spaces(const char* src) {
109-
return negate< spaces >(src);
110+
// Match optional_css_whitepace plus block_comments
111+
const char* optional_css_comments(const char* src) {
112+
return zero_plus< alternatives<spaces, line_comment, block_comment> >(src);
113+
}
114+
const char* css_comments(const char* src) {
115+
return one_plus< alternatives<spaces, line_comment, block_comment> >(src);
110116
}
111117

118+
// Match one backslash escaped char /\\./
112119
const char* backslash_something(const char* src) {
113120
return sequence< exactly<'\\'>, any_char >(src);
114121
}
@@ -153,7 +160,7 @@ namespace Sass {
153160
exactly < '+' >,
154161
sequence <
155162
exactly < '-' >,
156-
optional_spaces_and_comments,
163+
optional_css_whitespace,
157164
exactly< '-' >
158165
>
159166
>(src);
@@ -315,7 +322,7 @@ namespace Sass {
315322
}
316323
const char* elseif_directive(const char* src) {
317324
return sequence< else_directive,
318-
optional_spaces_and_comments,
325+
optional_css_whitespace,
319326
exactly< if_after_else_kwd > >(src);
320327
}
321328

@@ -493,25 +500,25 @@ namespace Sass {
493500
// Match CSS "!important" keyword.
494501
const char* important(const char* src) {
495502
return sequence< exactly<'!'>,
496-
optional_spaces_and_comments,
503+
optional_css_whitespace,
497504
exactly<important_kwd> >(src);
498505
}
499506
// Match CSS "!optional" keyword.
500507
const char* optional(const char* src) {
501508
return sequence< exactly<'!'>,
502-
optional_spaces_and_comments,
509+
optional_css_whitespace,
503510
exactly<optional_kwd> >(src);
504511
}
505512
// Match Sass "!default" keyword.
506513
const char* default_flag(const char* src) {
507514
return sequence< exactly<'!'>,
508-
optional_spaces_and_comments,
515+
optional_css_whitespace,
509516
exactly<default_kwd> >(src);
510517
}
511518
// Match Sass "!global" keyword.
512519
const char* global_flag(const char* src) {
513520
return sequence< exactly<'!'>,
514-
optional_spaces_and_comments,
521+
optional_css_whitespace,
515522
exactly<global_kwd> >(src);
516523
}
517524
// Match CSS pseudo-class/element prefixes.
@@ -610,27 +617,27 @@ namespace Sass {
610617
> >,
611618
zero_plus < sequence<
612619
exactly<'('>,
613-
optional_spaces_and_comments,
620+
optional_css_whitespace,
614621
optional < sequence<
615622
alternatives< variable, identifier_schema, identifier >,
616-
optional_spaces_and_comments,
623+
optional_css_whitespace,
617624
exactly<'='>,
618-
optional_spaces_and_comments,
625+
optional_css_whitespace,
619626
alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa >,
620627
zero_plus< sequence<
621-
optional_spaces_and_comments,
628+
optional_css_whitespace,
622629
exactly<','>,
623-
optional_spaces_and_comments,
630+
optional_css_whitespace,
624631
sequence<
625632
alternatives< variable, identifier_schema, identifier >,
626-
optional_spaces_and_comments,
633+
optional_css_whitespace,
627634
exactly<'='>,
628-
optional_spaces_and_comments,
635+
optional_css_whitespace,
629636
alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa >
630637
>
631638
> >
632639
> >,
633-
optional_spaces_and_comments,
640+
optional_css_whitespace,
634641
exactly<')'>
635642
> >
636643
>(src);
@@ -644,15 +651,15 @@ namespace Sass {
644651

645652
// const char* ie_args(const char* src) {
646653
// return sequence< alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by< '(', ')', true> >,
647-
// zero_plus< sequence< optional_spaces_and_comments, exactly<','>, optional_spaces_and_comments, alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by<'(', ')', true> > > > >(src);
654+
// zero_plus< sequence< optional_css_whitespace, exactly<','>, optional_css_whitespace, alternatives< ie_keyword_arg, value_schema, quoted_string, interpolant, number, identifier, delimited_by<'(', ')', true> > > > >(src);
648655
// }
649656

650657
const char* ie_keyword_arg(const char* src) {
651658
return sequence<
652659
alternatives< variable, identifier_schema, identifier >,
653-
optional_spaces_and_comments,
660+
optional_css_whitespace,
654661
exactly<'='>,
655-
optional_spaces_and_comments,
662+
optional_css_whitespace,
656663
alternatives< variable, identifier_schema, identifier, quoted_string, number, hexa >
657664
>(src);
658665
}

prelexer.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,16 @@ namespace Sass {
401401

402402
// Whitespace handling.
403403
const char* optional_spaces(const char* src);
404-
// const char* optional_comment(const char* src);
405-
const char* optional_spaces_and_comments(const char* src);
406-
const char* spaces_and_comments(const char* src);
407404
const char* no_spaces(const char* src);
408405

406+
// Match zero plus white-space or line_comments
407+
const char* optional_css_whitespace(const char* src);
408+
const char* css_whitespace(const char* src);
409+
// Match optional_css_whitepace plus block_comments
410+
const char* optional_css_comments(const char* src);
411+
const char* css_comments(const char* src);
412+
413+
// Match one backslash escaped char
409414
const char* backslash_something(const char* src);
410415

411416
// Match CSS css variables.

util.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,12 @@ namespace Sass {
380380

381381
bool peek_linefeed(const char* start)
382382
{
383-
if(*start == '\n' || *start == '\r') return true;;
384-
const char* linefeed = Prelexer::wspaces(start);
385-
if (linefeed == 0) return false;
386-
return *linefeed == '\n' || *linefeed == '\r';
383+
while (*start) {
384+
if (*start == '\n' || *start == '\r') return true;
385+
if (*start != ' ' && *start != '\t') return false;
386+
++ start;
387+
}
388+
return false;
387389
}
388390

389391
namespace Util {

0 commit comments

Comments
 (0)