Skip to content

Commit 8768c44

Browse files
committed
Merge pull request #1177 from mgreter/bugfix/issue_1158
Implement correct String Schema parsing
2 parents 348fde8 + 974ae42 commit 8768c44

File tree

5 files changed

+98
-52
lines changed

5 files changed

+98
-52
lines changed

context.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
#define PATH_SEP ':'
55
#endif
66

7+
#include <string>
8+
#include <cstdlib>
9+
#include <cstring>
10+
#include <iomanip>
11+
#include <sstream>
12+
#include <iostream>
13+
714
#include "ast.hpp"
815
#include "util.hpp"
916
#include "sass.h"
@@ -29,13 +36,6 @@
2936
#include "prelexer.hpp"
3037
#include "emitter.hpp"
3138

32-
#include <string>
33-
#include <cstdlib>
34-
#include <cstring>
35-
#include <iomanip>
36-
#include <sstream>
37-
#include <iostream>
38-
3939
namespace Sass {
4040
using namespace Constants;
4141
using namespace File;

debugger.hpp

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -383,9 +383,6 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
383383
cerr << endl;
384384
} else if (dynamic_cast<Variable*>(node)) {
385385
Variable* expression = dynamic_cast<Variable*>(node);
386-
cerr << ind << "Variable " << expression << " [" << expression->name() << "]";
387-
if (expression->is_delayed()) cerr << " [delayed]";
388-
cerr << endl;
389386
cerr << ind << "Variable " << expression;
390387
cerr << " (" << pstate_source_position(node) << ")";
391388
cerr << " [" << expression->name() << "]" << endl;
@@ -486,55 +483,37 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
486483
cerr << " [" << expression->value() << expression->unit() << "]" << endl;
487484
} else if (dynamic_cast<String_Quoted*>(node)) {
488485
String_Quoted* expression = dynamic_cast<String_Quoted*>(node);
489-
cerr << ind << "String_Quoted : " << expression << " [";
490-
cerr << prettyprint(expression->value()) << "]";
486+
cerr << ind << "String_Quoted " << expression;
487+
cerr << " (" << pstate_source_position(node) << ")";
488+
cerr << " [" << prettyprint(expression->value()) << "]";
491489
if (expression->is_delayed()) cerr << " [delayed]";
492490
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
493-
if (expression->quote_mark()) cerr << " [quote_mark]";
491+
if (expression->quote_mark()) cerr << " [quote_mark: " << expression->quote_mark() << "]";
494492
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
495-
cerr << ind << "String_Quoted : " << expression;
496-
cerr << " (" << pstate_source_position(node) << ")";
497-
cerr << " [" << prettyprint(expression->value()) << "]" <<
498-
(expression->is_delayed() ? " {delayed}" : "") <<
499-
(expression->sass_fix_1291() ? " {sass_fix_1291}" : "") <<
500-
(expression->quote_mark() != 0 ? " {qm:" + string(1, expression->quote_mark()) + "}" : "") <<
501-
" <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
502493
} else if (dynamic_cast<String_Constant*>(node)) {
503494
String_Constant* expression = dynamic_cast<String_Constant*>(node);
504-
cerr << ind << "String_Constant : " << expression;
495+
cerr << ind << "String_Constant " << expression;
496+
cerr << " " << expression->concrete_type() <<
497+
cerr << " (" << pstate_source_position(node) << ")";
505498
cerr << " [" << prettyprint(expression->value()) << "]";
506499
if (expression->is_delayed()) cerr << " [delayed]";
507500
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
508501
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
509-
cerr << ind << "String_Constant : " << expression;
510-
cerr << " (" << pstate_source_position(node) << ")";
511-
cerr << " [" << prettyprint(expression->value()) << "]" <<
512-
(expression->is_delayed() ? " {delayed}" : "") <<
513-
(expression->sass_fix_1291() ? " {sass_fix_1291}" : "") <<
514-
(expression->quote_mark() != 0 ? " {qm:" + string(1, expression->quote_mark()) + "}" : "") <<
515-
" <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
516502
} else if (dynamic_cast<String_Schema*>(node)) {
517503
String_Schema* expression = dynamic_cast<String_Schema*>(node);
518-
cerr << ind << "String_Schema " << expression << " [" << expression->concrete_type() << "]";
504+
cerr << ind << "String_Schema " << expression;
505+
cerr << " " << expression->concrete_type();
519506
if (expression->is_delayed()) cerr << " [delayed]";
520507
if (expression->has_interpolants()) cerr << " [has_interpolants]";
521508
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
522-
cerr << ind << "String_Schema " << expression;
523-
cerr << " (" << pstate_source_position(node) << ")";
524-
cerr << " " << expression->concrete_type() <<
525-
(expression->has_interpolants() ? " {has_interpolants}" : "") <<
526-
endl;
527509
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
528510
} else if (dynamic_cast<String*>(node)) {
529511
String* expression = dynamic_cast<String*>(node);
530-
cerr << ind << "String " << expression << expression->concrete_type();
531-
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
532-
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
533512
cerr << ind << "String " << expression;
513+
cerr << " " << expression->concrete_type();
534514
cerr << " (" << pstate_source_position(node) << ")";
535-
cerr << expression->concrete_type() <<
536-
" " << (expression->sass_fix_1291() ? "{sass_fix_1291}" : "") <<
537-
endl;
515+
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
516+
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
538517
} else if (dynamic_cast<Expression*>(node)) {
539518
Expression* expression = dynamic_cast<Expression*>(node);
540519
cerr << ind << "Expression " << expression;

eval.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#include <cstdlib>
2+
#include <cmath>
3+
#include <iostream>
4+
#include <iomanip>
5+
#include <typeinfo>
6+
17
#include "file.hpp"
28
#include "eval.hpp"
39
#include "ast.hpp"
@@ -11,12 +17,6 @@
1117
#include "prelexer.hpp"
1218
#include "parser.hpp"
1319

14-
#include <cstdlib>
15-
#include <cmath>
16-
#include <iostream>
17-
#include <iomanip>
18-
#include <typeinfo>
19-
2020
namespace Sass {
2121
using namespace std;
2222

parser.cpp

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -980,13 +980,25 @@ namespace Sass {
980980
return new (ctx.mem) Declaration(prop->pstate(), prop, parse_static_value()/*, lex<important>()*/);
981981
}
982982
else {
983-
Expression* list_ex = parse_list();
984-
if (List* list = dynamic_cast<List*>(list_ex)) {
985-
if (list->length() == 0 && !peek< exactly <'{'> >()) {
986-
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
983+
Expression* value;
984+
Selector_Lookahead lookahead = lookahead_for_value(position);
985+
if (lookahead.found) {
986+
if (lookahead.has_interpolants) {
987+
value = parse_value_schema(lookahead.found);
988+
} else {
989+
value = parse_list();
987990
}
988991
}
989-
return new (ctx.mem) Declaration(prop->pstate(), prop, list_ex/*, lex<important>()*/);
992+
else {
993+
value = parse_list();
994+
if (List* list = dynamic_cast<List*>(value)) {
995+
if (list->length() == 0 && !peek< exactly <'{'> >()) {
996+
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
997+
}
998+
}
999+
}
1000+
1001+
return new (ctx.mem) Declaration(prop->pstate(), prop, value/*, lex<important>()*/);
9901002
}
9911003
}
9921004

@@ -1503,7 +1515,10 @@ namespace Sass {
15031515
String_Schema* schema = new (ctx.mem) String_Schema(pstate);
15041516
size_t num_items = 0;
15051517
while (position < stop) {
1506-
if (lex< interpolant >()) {
1518+
if (lex< spaces >() && num_items) {
1519+
(*schema) << new (ctx.mem) String_Constant(pstate, " ");
1520+
}
1521+
else if (lex< interpolant >()) {
15071522
Token insides(Token(lexed.begin + 2, lexed.end - 1));
15081523
Expression* interp_node = Parser::from_token(insides, ctx, pstate).parse_list();
15091524
interp_node->is_interpolant(true);
@@ -2008,6 +2023,7 @@ namespace Sass {
20082023
(q = peek< class_name >(p)) ||
20092024
(q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
20102025
(q = peek< percentage >(p)) ||
2026+
(q = peek< variable >(p)) ||
20112027
(q = peek< dimension >(p)) ||
20122028
(q = peek< quoted_string >(p)) ||
20132029
(q = peek< exactly<'*'> >(p)) ||
@@ -2070,6 +2086,7 @@ namespace Sass {
20702086
(q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
20712087
(q = peek< percentage >(p)) ||
20722088
(q = peek< dimension >(p)) ||
2089+
(q = peek< variable >(p)) ||
20732090
(q = peek< quoted_string >(p)) ||
20742091
(q = peek< exactly<'*'> >(p)) ||
20752092
(q = peek< exactly<'('> >(p)) ||
@@ -2117,6 +2134,55 @@ namespace Sass {
21172134
return result;
21182135
}
21192136

2137+
2138+
Selector_Lookahead Parser::lookahead_for_value(const char* start)
2139+
{
2140+
const char* p = start ? start : position;
2141+
const char* q;
2142+
bool saw_interpolant = false;
2143+
bool saw_stuff = false;
2144+
2145+
while ((q = peek< identifier >(p)) ||
2146+
(q = peek< percentage >(p)) ||
2147+
(q = peek< dimension >(p)) ||
2148+
(q = peek< quoted_string >(p)) ||
2149+
(q = peek< variable >(p)) ||
2150+
(q = peek< exactly<'*'> >(p)) ||
2151+
(q = peek< exactly<'+'> >(p)) ||
2152+
(q = peek< exactly<'~'> >(p)) ||
2153+
(q = peek< exactly<'>'> >(p)) ||
2154+
(q = peek< exactly<','> >(p)) ||
2155+
(saw_stuff && (q = peek< exactly<'-'> >(p))) ||
2156+
(q = peek< binomial >(p)) ||
2157+
(q = peek< block_comment >(p)) ||
2158+
(q = peek< sequence< optional<sign>,
2159+
zero_plus<digit>,
2160+
exactly<'n'> > >(p)) ||
2161+
(q = peek< sequence< optional<sign>,
2162+
one_plus<digit> > >(p)) ||
2163+
(q = peek< number >(p)) ||
2164+
(q = peek< sequence< exactly<'&'>,
2165+
identifier_alnums > >(p)) ||
2166+
(q = peek< exactly<'&'> >(p)) ||
2167+
(q = peek< exactly<'%'> >(p)) ||
2168+
(q = peek< sequence< exactly<'.'>, interpolant > >(p)) ||
2169+
(q = peek< sequence< exactly<'#'>, interpolant > >(p)) ||
2170+
(q = peek< sequence< one_plus< exactly<'-'> >, interpolant > >(p)) ||
2171+
(q = peek< sequence< pseudo_prefix, interpolant > >(p)) ||
2172+
(q = peek< interpolant >(p)) ||
2173+
(q = peek< optional >(p))) {
2174+
p = q;
2175+
if (*(p - 1) == '}') saw_interpolant = true;
2176+
saw_stuff = true;
2177+
}
2178+
2179+
Selector_Lookahead result;
2180+
result.found = peek< alternatives< exactly<';'>, exactly<'}'>, exactly<'{'> > >(p) && saw_stuff ? p : 0;
2181+
result.has_interpolants = saw_interpolant;
2182+
2183+
return result;
2184+
}
2185+
21202186
void Parser::read_bom()
21212187
{
21222188
size_t skip = 0;

parser.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ namespace Sass {
270270

271271
void parse_block_comments(Block* block);
272272

273+
Selector_Lookahead lookahead_for_value(const char* start = 0);
273274
Selector_Lookahead lookahead_for_selector(const char* start = 0);
274275
Selector_Lookahead lookahead_for_extension_target(const char* start = 0);
275276

0 commit comments

Comments
 (0)