Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve interpolate parsing and unquote output #847

Merged
merged 3 commits into from
Feb 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion error_handling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Sass {

void error(string msg, ParserState pstate, Backtrace* bt)
{
if (!pstate.path.empty() && Prelexer::string_constant(pstate.path.c_str()))
if (!pstate.path.empty() && Prelexer::quoted_string(pstate.path.c_str()))
pstate.path = pstate.path.substr(1, pstate.path.size() - 1);

Backtrace top(bt, pstate, "");
Expand Down
56 changes: 50 additions & 6 deletions inspect.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "inspect.hpp"
#include "ast.hpp"
#include "context.hpp"
#include "utf8/checked.h"
#include <cmath>
#include <string>
#include <iostream>
Expand Down Expand Up @@ -768,17 +769,60 @@ namespace Sass {
if (s.length() == 1) {
if (s[0] == '"' || s[0] == '\'') return "";
}
char q;
if (*s.begin() == '"' && *s.rbegin() == '"') q = '"';
else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\'';
// char q;
if (*s.begin() == '"' && *s.rbegin() == '"') {} // q = '"';
else if (*s.begin() == '\'' && *s.rbegin() == '\'') {} // q = '\'';
else return s;
string t;
t.reserve(s.length()-2);

for (size_t i = 1, L = s.length()-1; i < L; ++i) {
// if we see a quote, we need to remove the preceding backslash from t
if (s[i-1] == '\\' && s[i] == q) t.erase(t.length()-1);
t.push_back(s[i]);

// implement the same strange ruby sass behavior
// an escape sequence can also mean a unicode char
if (s[i] == '\\') {

// skip it
++ i;

// escape length
size_t len = 0;

// parse as many sequence chars as possible
// ToDo: Check if ruby aborts after possible max
while (s[i + len] && isxdigit(s[i + len])) ++ len;

// hex string?
if (len == 0) {

// add next char
t.push_back(s[i]);

} else {

// convert the extracted hex string to code point value
// ToDo: Maybe we could do this without creating a substring
uint32_t cp = strtol(s.substr (i, len).c_str(), nullptr, 16);

// use a very simple approach to convert via utf8 lib
// maybe there is a more elegant way; maybe we shoud
// convert the whole output from string to a stream!?
// allocate memory for utf8 char and convert to utf8
unsigned char u[5] = {0,0,0,0,0}; utf8::append(cp, u);
for(size_t m = 0; u[m] && m < 5; m++) t.push_back(u[m]);

// skip some more chars?
if (len > 1) i += len - 1;

}
// EO if hex

} else {
// add single char
t.push_back(s[i]);
}
}

return t;
}

Expand Down
26 changes: 13 additions & 13 deletions parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ namespace Sass {
}
// ignore the @charset directive for now
else if (lex< exactly< charset_kwd > >()) {
lex< string_constant >();
lex< quoted_string >();
lex< one_plus< exactly<';'> > >();
}
else if (peek< at_keyword >()) {
Expand Down Expand Up @@ -164,7 +164,7 @@ namespace Sass {
Import* imp = new (ctx.mem) Import(pstate);
bool first = true;
do {
if (lex< string_constant >()) {
if (lex< quoted_string >()) {
string import_path(lexed);

// struct Sass_Options opt = sass_context_get_options(ctx)
Expand Down Expand Up @@ -514,10 +514,10 @@ namespace Sass {
return seq;
}
}
if (sawsomething && lex< sequence< negate< functional >, alternatives< identifier_fragment, universal, string_constant, dimension, percentage, number > > >()) {
if (sawsomething && lex< sequence< negate< functional >, alternatives< identifier_fragment, universal, quoted_string, dimension, percentage, number > > >()) {
// saw an ampersand, then allow type selectors with arbitrary number of hyphens at the beginning
(*seq) << new (ctx.mem) Type_Selector(pstate, lexed);
} else if (lex< sequence< negate< functional >, alternatives< type_selector, universal, string_constant, dimension, percentage, number > > >()) {
} else if (lex< sequence< negate< functional >, alternatives< type_selector, universal, quoted_string, dimension, percentage, number > > >()) {
// if you see a type selector
(*seq) << new (ctx.mem) Type_Selector(pstate, lexed);
sawsomething = true;
Expand Down Expand Up @@ -546,7 +546,7 @@ namespace Sass {
if (lex< id_name >() || lex< class_name >()) {
return new (ctx.mem) Selector_Qualifier(pstate, lexed);
}
else if (lex< string_constant >() || lex< number >()) {
else if (lex< quoted_string >() || lex< number >()) {
return new (ctx.mem) Type_Selector(pstate, lexed);
}
else if (peek< pseudo_not >()) {
Expand Down Expand Up @@ -619,7 +619,7 @@ namespace Sass {
lex< identifier >();
expr = new (ctx.mem) String_Constant(p, lexed);
}
else if (lex< string_constant >()) {
else if (lex< quoted_string >()) {
expr = new (ctx.mem) String_Constant(p, lexed);
}
else if (peek< exactly<')'> >()) {
Expand Down Expand Up @@ -661,7 +661,7 @@ namespace Sass {
if (lex< identifier >()) {
value = new (ctx.mem) String_Constant(p, lexed, true);
}
else if (lex< string_constant >()) {
else if (lex< quoted_string >()) {
value = parse_interpolated_chunk(lexed);
}
else {
Expand Down Expand Up @@ -795,7 +795,7 @@ namespace Sass {
}
// ignore the @charset directive for now
else if (lex< exactly< charset_kwd > >()) {
lex< string_constant >();
lex< quoted_string >();
lex< one_plus< exactly<';'> > >();
}
else if (peek< at_keyword >()) {
Expand Down Expand Up @@ -1209,7 +1209,7 @@ namespace Sass {
if (lex< number >())
{ return new (ctx.mem) Textual(pstate, Textual::NUMBER, lexed); }

if (peek< string_constant >())
if (peek< quoted_string >())
{ return parse_string(); }

if (lex< variable >())
Expand Down Expand Up @@ -1278,7 +1278,7 @@ namespace Sass {

String* Parser::parse_string()
{
lex< string_constant >();
lex< quoted_string >();
Token str(lexed);
return parse_interpolated_chunk(str);
// const char* i = str.begin;
Expand Down Expand Up @@ -1408,7 +1408,7 @@ namespace Sass {
else if (lex< hex >()) {
(*schema) << new (ctx.mem) Textual(pstate, Textual::HEX, lexed);
}
else if (lex< string_constant >()) {
else if (lex< quoted_string >()) {
(*schema) << new (ctx.mem) String_Constant(pstate, lexed);
if (!num_items) schema->quote_mark(*lexed.begin);
}
Expand Down Expand Up @@ -1875,7 +1875,7 @@ namespace Sass {
(q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
(q = peek< percentage >(p)) ||
(q = peek< dimension >(p)) ||
(q = peek< string_constant >(p)) ||
(q = peek< quoted_string >(p)) ||
(q = peek< exactly<'*'> >(p)) ||
(q = peek< exactly<'('> >(p)) ||
(q = peek< exactly<')'> >(p)) ||
Expand Down Expand Up @@ -1933,7 +1933,7 @@ namespace Sass {
(q = peek< sequence< pseudo_prefix, identifier > >(p)) ||
(q = peek< percentage >(p)) ||
(q = peek< dimension >(p)) ||
(q = peek< string_constant >(p)) ||
(q = peek< quoted_string >(p)) ||
(q = peek< exactly<'*'> >(p)) ||
(q = peek< exactly<'('> >(p)) ||
(q = peek< exactly<')'> >(p)) ||
Expand Down
Loading