From 9d07a48cedf58906f5c344152b591f9485146610 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Sat, 7 Mar 2015 03:12:07 +0100 Subject: [PATCH] Add improvements to interpolate parsing --- parser.cpp | 12 ++++++------ prelexer.cpp | 4 ++-- prelexer.hpp | 19 ++++++++++++++++--- util.cpp | 5 ++++- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/parser.cpp b/parser.cpp index f0ed5c5767..a736557586 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1273,7 +1273,7 @@ namespace Sass { { const char* i = chunk.begin; // see if there any interpolants - const char* p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly > >(i, chunk.end); + const char* p = find_first_in_interval< exactly >(i, chunk.end); if (!p) { String_Quoted* str_quoted = new (ctx.mem) String_Quoted(pstate, string(i, chunk.end)); if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*'); @@ -1283,7 +1283,7 @@ namespace Sass { String_Schema* schema = new (ctx.mem) String_Schema(pstate); while (i < chunk.end) { - p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly > >(i, chunk.end); + p = find_first_in_interval< exactly >(i, chunk.end); if (p) { if (i < p) { // accumulate the preceding segment if it's nonempty @@ -1338,7 +1338,7 @@ namespace Sass { Token str(lexed); const char* i = str.begin; // see if there any interpolants - const char* p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly > >(str.begin, str.end); + const char* p = find_first_in_interval< exactly >(str.begin, str.end); if (!p) { String_Constant* str_node = new (ctx.mem) String_Constant(pstate, normalize_wspace(string(str.begin, str.end))); str_node->is_delayed(true); @@ -1347,7 +1347,7 @@ namespace Sass { String_Schema* schema = new (ctx.mem) String_Schema(pstate); while (i < str.end) { - p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly > >(i, str.end); + p = find_first_in_interval< exactly >(i, str.end); if (p) { if (i < p) { (*schema) << new (ctx.mem) String_Constant(pstate, string(i, p)); // accumulate the preceding segment if it's nonempty @@ -1474,14 +1474,14 @@ namespace Sass { Token id(lexed); const char* i = id.begin; // see if there any interpolants - const char* p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly > >(id.begin, id.end); + const char* p = find_first_in_interval< exactly >(id.begin, id.end); if (!p) { return new (ctx.mem) String_Quoted(pstate, string(id.begin, id.end)); } String_Schema* schema = new (ctx.mem) String_Schema(pstate); while (i < id.end) { - p = find_first_in_interval< sequence< negate< exactly<'\\'> >, exactly > >(i, id.end); + p = find_first_in_interval< exactly >(i, id.end); if (p) { if (i < p) { // accumulate the preceding segment if it's nonempty diff --git a/prelexer.cpp b/prelexer.cpp index f3de77f3e7..a3a7a3e541 100644 --- a/prelexer.cpp +++ b/prelexer.cpp @@ -167,7 +167,7 @@ namespace Sass { zero_plus < alternatives < // skip all escaped chars first - sequence < exactly < '\\' >, any_char >, + backslash_something, // skip interpolants interpolant, // skip non delimiters @@ -186,7 +186,7 @@ namespace Sass { zero_plus < alternatives < // skip all escaped chars first - sequence < exactly < '\\' >, any_char >, + backslash_something, // skip interpolants interpolant, // skip non delimiters diff --git a/prelexer.hpp b/prelexer.hpp index e0950b5061..fa4953481a 100644 --- a/prelexer.hpp +++ b/prelexer.hpp @@ -565,8 +565,11 @@ namespace Sass { } template const char* find_first_in_interval(const char* beg, const char* end) { + bool esc = false; while ((beg < end) && *beg) { - if (mx(beg)) return beg; + if (esc) esc = false; + else if (*beg == '\\') esc = true; + else if (mx(beg)) return beg; ++beg; } return 0; @@ -574,8 +577,11 @@ namespace Sass { template unsigned int count_interval(const char* beg, const char* end) { unsigned int counter = 0; + bool esc = false; while (beg < end && *beg) { - if (*beg == c) ++counter; + if (esc) esc = false; + else if (*beg == '\\') esc = true; + else if (*beg == c) ++counter; ++beg; } return counter; @@ -583,9 +589,16 @@ namespace Sass { template unsigned int count_interval(const char* beg, const char* end) { unsigned int counter = 0; + bool esc = false; while (beg < end && *beg) { const char* p; - if ((p = mx(beg))) { + if (esc) { + esc = false; + ++beg; + } else if (*beg == '\\') { + esc = true; + ++beg; + } else if ((p = mx(beg))) { ++counter; beg = p; } diff --git a/util.cpp b/util.cpp index 64feda300e..f6a89db71b 100644 --- a/util.cpp +++ b/util.cpp @@ -106,7 +106,10 @@ namespace Sass { out += i; } } - if (esc) out += 'Z'; + // happens when parsing does not correctly skip + // over escaped sequences for ie. interpolations + // one example: foo\#{interpolate} + // if (esc) out += '\\'; return out; }