Skip to content

Commit 0633108

Browse files
committed
Implement case modifier for attribute selector
1 parent 1075f5c commit 0633108

File tree

9 files changed

+65
-6
lines changed

9 files changed

+65
-6
lines changed

src/ast.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,14 +2532,16 @@ namespace Sass {
25322532
ADD_CONSTREF(std::string, matcher)
25332533
// this cannot be changed to obj atm!!!!!!????!!!!!!!
25342534
ADD_PROPERTY(String_Obj, value) // might be interpolated
2535+
ADD_PROPERTY(char, modifier);
25352536
public:
2536-
Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v)
2537-
: Simple_Selector(pstate, n), matcher_(m), value_(v)
2537+
Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o = 0)
2538+
: Simple_Selector(pstate, n), matcher_(m), value_(v), modifier_(o)
25382539
{ simple_type(ATTR_SEL); }
25392540
Attribute_Selector(const Attribute_Selector* ptr)
25402541
: Simple_Selector(ptr),
25412542
matcher_(ptr->matcher_),
2542-
value_(ptr->value_)
2543+
value_(ptr->value_),
2544+
modifier_(ptr->modifier_)
25432545
{ simple_type(ATTR_SEL); }
25442546
virtual size_t hash()
25452547
{

src/emitter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ namespace Sass {
105105
wbuf.buffer = text + wbuf.buffer;
106106
}
107107

108+
// append a single char to the buffer
109+
void Emitter::append_char(const char chr)
110+
{
111+
// write space/lf
112+
flush_schedules();
113+
// add to buffer
114+
wbuf.buffer += chr;
115+
// account for data in source-maps
116+
wbuf.smap.append(Offset(chr));
117+
}
118+
108119
// append some text or token to the buffer
109120
void Emitter::append_string(const std::string& text)
110121
{

src/emitter.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ namespace Sass {
6666
void prepend_output(const OutputBuffer& out);
6767
// append some text or token to the buffer
6868
void append_string(const std::string& text);
69+
// append a single character to buffer
70+
void append_char(const char chr);
6971
// append some white-space only text
7072
void append_wspace(const std::string& text);
7173
// append some text or token to the buffer

src/inspect.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,10 @@ namespace Sass {
935935
}
936936
}
937937
add_close_mapping(s);
938+
if (s->modifier() != 0) {
939+
append_mandatory_space();
940+
append_char(s->modifier());
941+
}
938942
append_string("]");
939943
}
940944

src/lexer.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ namespace Sass {
110110
}
111111

112112

113+
// Match a single character literal.
114+
// Regex equivalent: /(?:x)/i
115+
// only define lower case alpha chars
116+
template <char chr>
117+
const char* insensitive(const char* src) {
118+
return *src == chr || *src+32 == chr ? src + 1 : 0;
119+
}
120+
113121
// Match the full string literal.
114122
// Regex equivalent: /(?:literal)/i
115123
// only define lower case alpha chars

src/parser.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -944,12 +944,28 @@ namespace Sass {
944944
return 0;
945945
}
946946

947+
const char* Parser::re_attr_sensitive_close(const char* src)
948+
{
949+
return alternatives < exactly<']'>, exactly<'/'> >(src);
950+
}
951+
952+
const char* Parser::re_attr_insensitive_close(const char* src)
953+
{
954+
return sequence < insensitive<'i'>, re_attr_sensitive_close >(src);
955+
}
956+
947957
Attribute_Selector_Obj Parser::parse_attribute_selector()
948958
{
949959
ParserState p = pstate;
950960
if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector", pstate);
951961
std::string name(lexed);
952-
if (lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0);
962+
if (lex_css< re_attr_sensitive_close >()) {
963+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, 0);
964+
}
965+
else if (lex_css< re_attr_insensitive_close >()) {
966+
char modifier = lexed.begin[0];
967+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, modifier);
968+
}
953969
if (!lex_css< alternatives< exact_match, class_match, dash_match,
954970
prefix_match, suffix_match, substring_match > >()) {
955971
error("invalid operator in attribute selector for " + name, pstate);
@@ -967,8 +983,15 @@ namespace Sass {
967983
error("expected a string constant or identifier in attribute selector for " + name, pstate);
968984
}
969985

970-
if (!lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) error("unterminated attribute selector for " + name, pstate);
971-
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value);
986+
if (lex_css< re_attr_sensitive_close >()) {
987+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, 0);
988+
}
989+
else if (lex_css< re_attr_insensitive_close >()) {
990+
char modifier = lexed.begin[0];
991+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
992+
}
993+
error("unterminated attribute selector for " + name, pstate);
994+
return NULL; // to satisfy compilers (error must not return)
972995
}
973996

974997
/* parse block comment and add to block */

src/parser.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ namespace Sass {
379379
Number_Ptr lexed_percentage(const std::string& parsed) { return lexed_percentage(pstate, parsed); };
380380
Expression_Ptr lexed_hex_color(const std::string& parsed) { return lexed_hex_color(pstate, parsed); };
381381

382+
static const char* re_attr_sensitive_close(const char* src);
383+
static const char* re_attr_insensitive_close(const char* src);
384+
382385
};
383386

384387
size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len);

src/position.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
namespace Sass {
55

66

7+
Offset::Offset(const char chr)
8+
: line(chr == '\n' ? 1 : 0),
9+
column(chr == '\n' ? 0 : 1)
10+
{}
11+
712
Offset::Offset(const char* string)
813
: line(0), column(0)
914
{

src/position.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Sass {
1111
class Offset {
1212

1313
public: // c-tor
14+
Offset(const char chr);
1415
Offset(const char* string);
1516
Offset(const std::string& text);
1617
Offset(const size_t line, const size_t column);

0 commit comments

Comments
 (0)