From 6d4f9a216c68ed9d1c93855a3864206936cfd937 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Sat, 9 Jan 2016 19:31:26 +0100 Subject: [PATCH] improve parsing of special functions --- src/constants.cpp | 1 + src/constants.hpp | 1 + src/eval.cpp | 7 +++---- src/prelexer.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- src/prelexer.hpp | 4 ++++ 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/constants.cpp b/src/constants.cpp index cffc519773..f52eda44f7 100644 --- a/src/constants.cpp +++ b/src/constants.cpp @@ -87,6 +87,7 @@ namespace Sass { extern const char odd_kwd[] = "odd"; extern const char progid_kwd[] = "progid"; extern const char expression_kwd[] = "expression"; + extern const char calc_fn_kwd[] = "calc"; extern const char calc_kwd[] = "calc("; extern const char moz_calc_kwd[] = "-moz-calc("; extern const char webkit_calc_kwd[] = "-webkit-calc("; diff --git a/src/constants.hpp b/src/constants.hpp index 21d416025d..99a410de86 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -89,6 +89,7 @@ namespace Sass { extern const char progid_kwd[]; extern const char expression_kwd[]; extern const char calc_kwd[]; + extern const char calc_fn_kwd[]; extern const char moz_calc_kwd[]; extern const char webkit_calc_kwd[]; extern const char ms_calc_kwd[]; diff --git a/src/eval.cpp b/src/eval.cpp index 0d8a2c42fe..fa42c42650 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -882,10 +882,9 @@ namespace Sass { bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this); Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`"); exp.backtrace_stack.push_back(&here); - // if it's user-defined, eval the body - if (body) { result = body->perform(this); } - // if it's native, invoke the underlying CPP function - else { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace()); } + // eval the body if user-defined or special, invoke underlying CPP function if native + if (body && !Prelexer::re_special_fun(c->name().c_str())) { result = body->perform(this); } + else if (func) { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace()); } if (!result) error(std::string("Function ") + c->name() + " did not return a value", c->pstate()); exp.backtrace_stack.pop_back(); } diff --git a/src/prelexer.cpp b/src/prelexer.cpp index f50519ddd8..79c16519be 100644 --- a/src/prelexer.cpp +++ b/src/prelexer.cpp @@ -296,7 +296,7 @@ namespace Sass { bool was_number = false; const char* pos = src; while (src) { - if (pos = alternatives < quoted_string, identifier, percentage, hex >(src)) { + if ((pos = alternatives < quoted_string, identifier, percentage, hex >(src))) { was_number = false; src = pos; } else if (!was_number && !exactly<'+'>(src) && (pos = alternatives < dimension, number >(src))) { @@ -1129,6 +1129,41 @@ namespace Sass { return sequence< number, optional_spaces, exactly<'/'>, optional_spaces, number >(src); } + // lexer special_fn: these functions cannot be overloaded + // (/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i) + const char* re_special_fun(const char* src) { + return sequence < + optional < + sequence < + exactly <'-'>, + one_plus < + alternatives < + alpha, + exactly <'+'>, + exactly <'-'> + > + > + > + >, + alternatives < + exactly < calc_fn_kwd >, + exactly < expression_kwd >, + sequence < + sequence < + exactly < progid_kwd >, + exactly <':'> + >, + zero_plus < + alternatives < + char_range <'a', 'z'>, + exactly <'.'> + > + > + > + > + >(src); + } + template const char* padded_token(const char* src) { @@ -1159,5 +1194,13 @@ namespace Sass { return pos; } + template + const char* char_range(const char* src) + { + if (*src < min) return 0; + if (*src > max) return 0; + return src + 1; + } + } } diff --git a/src/prelexer.hpp b/src/prelexer.hpp index e7156f3723..d22ccac170 100644 --- a/src/prelexer.hpp +++ b/src/prelexer.hpp @@ -253,6 +253,7 @@ namespace Sass { const char* re_nothing(const char* src); const char* re_type_selector2(const char* src); + const char* re_special_fun(const char* src); const char* kwd_warn(const char* src); const char* kwd_err(const char* src); @@ -423,6 +424,9 @@ namespace Sass { template const char* minmax_range(const char* src); + template + const char* char_range(const char* src); + } }