Skip to content

Commit 09f5d07

Browse files
committed
Remove Sass_List_Delimiter in favour of an is_bracketed property
The list delimiter property only existed as a way to preserve parser state on the node in order to reused the existing `parse_list` function. This PR instead adds a `parse_bracketed_list` function to explicitly parse bracketed lists and sets the `is_bracketed` property on the `List` node. It turns out this is exactly what Ruby Sass does.
1 parent 46f5244 commit 09f5d07

File tree

7 files changed

+72
-37
lines changed

7 files changed

+72
-37
lines changed

include/sass/values.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,6 @@ enum Sass_Separator {
3535
SASS_HASH
3636
};
3737

38-
// Tags for denoting Sass list delimiters
39-
enum Sass_List_Delimiter {
40-
SASS_NO_DELIMITER,
41-
SASS_PARENTHESIS,
42-
SASS_BRACKETS
43-
};
44-
4538
// Value Operators
4639
enum Sass_OP {
4740
AND, OR, // logical connectives

src/ast.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,25 +1047,24 @@ namespace Sass {
10471047
private:
10481048
ADD_PROPERTY(enum Sass_Separator, separator)
10491049
ADD_PROPERTY(bool, is_arglist)
1050-
ADD_PROPERTY(enum Sass_List_Delimiter, delimiter)
1050+
ADD_PROPERTY(bool, is_bracketed)
10511051
ADD_PROPERTY(bool, from_selector)
10521052
public:
10531053
List(ParserState pstate,
1054-
size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false,
1055-
enum Sass_List_Delimiter delimiter = SASS_NO_DELIMITER)
1054+
size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false)
10561055
: Value(pstate),
10571056
Vectorized<Expression_Obj>(size),
10581057
separator_(sep),
10591058
is_arglist_(argl),
1060-
delimiter_(delimiter),
1059+
is_bracketed_(bracket),
10611060
from_selector_(false)
10621061
{ concrete_type(LIST); }
10631062
List(const List* ptr)
10641063
: Value(ptr),
10651064
Vectorized<Expression_Obj>(*ptr),
10661065
separator_(ptr->separator_),
10671066
is_arglist_(ptr->is_arglist_),
1068-
delimiter_(ptr->delimiter_),
1067+
is_bracketed_(ptr->is_bracketed_),
10691068
from_selector_(ptr->from_selector_)
10701069
{ concrete_type(LIST); }
10711070
std::string type() { return is_arglist_ ? "arglist" : "list"; }
@@ -1074,7 +1073,6 @@ namespace Sass {
10741073
return separator() == SASS_SPACE ?
10751074
" " : (compressed ? "," : ", ");
10761075
}
1077-
bool is_bracketed() const { return delimiter() == SASS_BRACKETS; }
10781076
bool is_invisible() const { return empty() && !is_bracketed(); }
10791077
Expression_Obj value_at_index(size_t i);
10801078

src/debugger.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,11 +595,11 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
595595
std::cerr << " (" << pstate_source_position(node) << ")";
596596
std::cerr << " (" << expression->length() << ") " <<
597597
(expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map " : "Space ") <<
598-
(expression->delimiter() == SASS_PARENTHESIS ? "Parenthesis " : expression->delimiter() == SASS_BRACKETS ? "Bracket " : "None ") <<
599598
" [delayed: " << expression->is_delayed() << "] " <<
600599
" [interpolant: " << expression->is_interpolant() << "] " <<
601600
" [listized: " << expression->from_selector() << "] " <<
602601
" [arglist: " << expression->is_arglist() << "] " <<
602+
" [bracketed: " << expression->is_bracketed() << "] " <<
603603
" [expanded: " << expression->is_expanded() << "] " <<
604604
" [hash: " << expression->hash() << "] " <<
605605
std::endl;

src/eval.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ namespace Sass {
462462
l->length(),
463463
l->separator(),
464464
l->is_arglist(),
465-
l->delimiter());
465+
l->is_bracketed());
466466
for (size_t i = 0, L = l->length(); i < L; ++i) {
467467
ll->append((*l)[i]->perform(this));
468468
}

src/functions.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,7 @@ namespace Sass {
13041304
if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
13051305
double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
13061306
if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
1307-
List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->delimiter());
1307+
List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->is_bracketed());
13081308
for (size_t i = 0, L = l->length(); i < L; ++i) {
13091309
result->append(((i == index) ? v : (*l)[i]));
13101310
}
@@ -1340,12 +1340,12 @@ namespace Sass {
13401340
String_Constant_Obj sep = ARG("$separator", String_Constant);
13411341
enum Sass_Separator sep_val = (l1 ? l1->separator() : SASS_SPACE);
13421342
Value* bracketed = ARG("$bracketed", Value);
1343-
enum Sass_List_Delimiter delimiter = (l1 ? l1->delimiter() : SASS_NO_DELIMITER);
1343+
bool is_bracketed = (l1 ? l1->is_bracketed() : false);
13441344
if (!l1) {
13451345
l1 = SASS_MEMORY_NEW(List, pstate, 1);
13461346
l1->append(ARG("$list1", Expression));
13471347
sep_val = (l2 ? l2->separator() : SASS_SPACE);
1348-
delimiter = (l2 ? l2->delimiter() : SASS_NO_DELIMITER);
1348+
is_bracketed = (l2 ? l2->is_bracketed() : false);
13491349
}
13501350
if (!l2) {
13511351
l2 = SASS_MEMORY_NEW(List, pstate, 1);
@@ -1366,9 +1366,9 @@ namespace Sass {
13661366
String_Constant_Obj bracketed_as_str = SASS_MEMORY_CAST_PTR(String_Constant, bracketed);
13671367
bool bracketed_is_auto = bracketed_as_str && unquote(bracketed_as_str->value()) == "auto";
13681368
if (!bracketed_is_auto) {
1369-
delimiter = bracketed->is_false() ? SASS_NO_DELIMITER : SASS_BRACKETS;
1369+
is_bracketed = !bracketed->is_false();
13701370
}
1371-
List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val, false, delimiter);
1371+
List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val, false, is_bracketed);
13721372
result->concat(&l1);
13731373
result->concat(&l2);
13741374
return result.detach();

src/parser.cpp

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,13 +1000,8 @@ namespace Sass {
10001000
List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
10011001

10021002
// it's not a map so return the lexed value as a list value
1003-
if (!lex_css< exactly<':'> >()) {
1004-
List_Obj list = SASS_MEMORY_CAST(List, key);
1005-
if (list && list->delimiter() == SASS_NO_DELIMITER) {
1006-
list->delimiter(SASS_PARENTHESIS);
1007-
}
1008-
return key;
1009-
}
1003+
if (!lex_css< exactly<':'> >())
1004+
{ return key; }
10101005

10111006
Expression_Obj value = parse_space_list();
10121007

@@ -1037,6 +1032,62 @@ namespace Sass {
10371032
return &map;
10381033
}
10391034

1035+
Expression_Obj Parser::parse_bracket_list()
1036+
{
1037+
// check if we have an empty list
1038+
// return the empty list as such
1039+
if (peek_css<
1040+
exactly<']'>
1041+
>(position))
1042+
{
1043+
// return an empty list (nothing to delay)
1044+
return SASS_MEMORY_NEW(List, pstate, 0, SASS_SPACE, false, true);
1045+
}
1046+
1047+
bool has_paren = peek_css< exactly<'('> >();
1048+
1049+
// now try to parse a space list
1050+
Expression_Obj list = parse_space_list();
1051+
// if it's a singleton, return it (don't wrap it)
1052+
if (!peek_css< exactly<','> >(position)) {
1053+
List_Obj l = SASS_MEMORY_CAST(List, list);
1054+
if (!l || l->is_bracketed() || has_paren) {
1055+
List_Obj bracketed_list = SASS_MEMORY_NEW(List, pstate, 1, SASS_SPACE, false, true);
1056+
bracketed_list->append(&list);
1057+
return &bracketed_list;
1058+
}
1059+
l->is_bracketed(&list);
1060+
return &l;
1061+
}
1062+
1063+
// if we got so far, we actually do have a comma list
1064+
List_Obj bracketed_list = SASS_MEMORY_NEW(List, pstate, 2, SASS_COMMA, false, true);
1065+
// wrap the first expression
1066+
bracketed_list->append(list);
1067+
1068+
while (lex_css< exactly<','> >())
1069+
{
1070+
// check for abort condition
1071+
if (peek_css< alternatives <
1072+
exactly<';'>,
1073+
exactly<'}'>,
1074+
exactly<'{'>,
1075+
exactly<')'>,
1076+
exactly<']'>,
1077+
exactly<':'>,
1078+
end_of_file,
1079+
exactly<ellipsis>,
1080+
default_flag,
1081+
global_flag
1082+
> >(position)
1083+
) { break; }
1084+
// otherwise add another expression
1085+
bracketed_list->append(parse_space_list());
1086+
}
1087+
// return the list
1088+
return &bracketed_list;
1089+
}
1090+
10401091
// parse list returns either a space separated list,
10411092
// a comma separated list or any bare expression found.
10421093
// so to speak: we unwrap items from lists if possible here!
@@ -1339,18 +1390,10 @@ namespace Sass {
13391390
}
13401391
else if (lex_css< exactly<'['> >()) {
13411392
// explicit bracketed
1342-
Expression_Obj value = parse_list();
1393+
Expression_Obj value = parse_bracket_list();
13431394
// lex the expected closing square bracket
13441395
if (!lex_css< exactly<']'> >()) error("unclosed squared bracket", pstate);
1345-
// fix delimiter
1346-
List_Obj list = SASS_MEMORY_CAST(List, value);
1347-
if (!list || list->delimiter() != SASS_NO_DELIMITER) {
1348-
List_Ptr outer_list = SASS_MEMORY_NEW(List, pstate, 1, SASS_SPACE, false, SASS_BRACKETS);
1349-
outer_list->append(&value);
1350-
return outer_list;
1351-
}
1352-
list->delimiter(SASS_BRACKETS);
1353-
return value;
1396+
return &value;
13541397
}
13551398
// string may be interpolated
13561399
// if (lex< quoted_string >()) {

src/parser.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ namespace Sass {
257257
bool parse_number_prefix();
258258
Declaration_Obj parse_declaration();
259259
Expression_Obj parse_map();
260+
Expression_Obj parse_bracket_list();
260261
Expression_Obj parse_list(bool delayed = false);
261262
Expression_Obj parse_comma_list(bool delayed = false);
262263
Expression_Obj parse_space_list();

0 commit comments

Comments
 (0)