From 98d8d5dadacc3cd07c738b3772f56317a7a306e7 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Thu, 4 Apr 2019 19:59:24 +0100 Subject: [PATCH] Error on incomplete `@supports` clause in parser Fixes #2786 Spec added in https://github.com/sass/sass-spec/pull/1370 --- src/parser.cpp | 38 +++++++++++++++++++------------------- src/parser.hpp | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index 2736a97372..cfb389d48f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2415,10 +2415,7 @@ namespace Sass { // these are very similar to media blocks Supports_Block_Obj Parser::parse_supports_directive() { - Supports_Condition_Obj cond = parse_supports_condition(); - if (!cond) { - css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", false); - } + Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/true); // create the ast node object for the support queries Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond); // additional block is mandatory @@ -2430,12 +2427,12 @@ namespace Sass { // parse one query operation // may encounter nested queries - Supports_Condition_Obj Parser::parse_supports_condition() + Supports_Condition_Obj Parser::parse_supports_condition(bool top_level) { lex < css_whitespace >(); Supports_Condition_Obj cond; if ((cond = parse_supports_negation())) return cond; - if ((cond = parse_supports_operator())) return cond; + if ((cond = parse_supports_operator(top_level))) return cond; if ((cond = parse_supports_interpolation())) return cond; return cond; } @@ -2443,13 +2440,13 @@ namespace Sass { Supports_Condition_Obj Parser::parse_supports_negation() { if (!lex < kwd_not >()) return {}; - Supports_Condition_Obj cond = parse_supports_condition_in_parens(); + Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/true); return SASS_MEMORY_NEW(Supports_Negation, pstate, cond); } - Supports_Condition_Obj Parser::parse_supports_operator() + Supports_Condition_Obj Parser::parse_supports_operator(bool top_level) { - Supports_Condition_Obj cond = parse_supports_condition_in_parens(); + Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level); if (cond.isNull()) return {}; while (true) { @@ -2458,7 +2455,7 @@ namespace Sass { else if(!lex < kwd_or >()) { break; } lex < css_whitespace >(); - Supports_Condition_Obj right = parse_supports_condition_in_parens(); + Supports_Condition_Obj right = parse_supports_condition_in_parens(/*parens_required=*/true); // Supports_Condition* cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast(cond)); cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op); @@ -2496,21 +2493,24 @@ namespace Sass { return cond; } - Supports_Condition_Obj Parser::parse_supports_condition_in_parens() + Supports_Condition_Obj Parser::parse_supports_condition_in_parens(bool parens_required) { Supports_Condition_Obj interp = parse_supports_interpolation(); if (interp != 0) return interp; - if (!lex < exactly <'('> >()) return {}; + if (!lex < exactly <'('> >()) { + if (parens_required) { + css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", /*trim=*/false); + } else { + return {}; + } + } lex < css_whitespace >(); - Supports_Condition_Obj cond = parse_supports_condition(); - if (cond != 0) { - if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration"); - } else { - cond = parse_supports_declaration(); - if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration"); - } + Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/false); + if (cond.isNull()) cond = parse_supports_declaration(); + if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration"); + lex < css_whitespace >(); return cond; } diff --git a/src/parser.hpp b/src/parser.hpp index 33f51175d3..8b74cb51cc 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -312,12 +312,12 @@ namespace Sass { Media_Query_Obj parse_media_query(); Media_Query_Expression_Obj parse_media_expression(); Supports_Block_Obj parse_supports_directive(); - Supports_Condition_Obj parse_supports_condition(); + Supports_Condition_Obj parse_supports_condition(bool top_level); Supports_Condition_Obj parse_supports_negation(); - Supports_Condition_Obj parse_supports_operator(); + Supports_Condition_Obj parse_supports_operator(bool top_level); Supports_Condition_Obj parse_supports_interpolation(); Supports_Condition_Obj parse_supports_declaration(); - Supports_Condition_Obj parse_supports_condition_in_parens(); + Supports_Condition_Obj parse_supports_condition_in_parens(bool parens_required); At_Root_Block_Obj parse_at_root_block(); At_Root_Query_Obj parse_at_root_query(); String_Schema_Obj parse_almost_any_value();