From 2c5846b5f8042c4269926d1dba2e29fafe4a5165 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sun, 19 Oct 2008 21:49:05 +0000 Subject: Fix parsing of combinators: the CSS 2.1 spec grammar contains inaccuracies -- combinators may be preceded by whitespace. Fix handling of whitespace after a selector list: again, the CSS 2.1 grammar isn't accurate here. svn path=/trunk/libcss/; revision=5603 --- src/parse/css21.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/parse/css21.c b/src/parse/css21.c index 501b4b6..5455eb6 100644 --- a/src/parse/css21.c +++ b/src/parse/css21.c @@ -747,26 +747,38 @@ css_error parseCombinator(css_css21 *c, const parserutils_vector *vector, int *ctx, css_combinator *result) { const css_token *token; + css_combinator comb = CSS_COMBINATOR_NONE; - /* combinator -> '+' ws | '>' ws | ws1 */ + /* combinator -> ws '+' ws | ws '>' ws | ws1 */ UNUSED(c); - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL) - return CSS_INVALID; + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL) { + if (tokenIsChar(token, '+')) + comb = CSS_COMBINATOR_SIBLING; + else if (tokenIsChar(token, '>')) + comb = CSS_COMBINATOR_PARENT; + else if (token->type == CSS_TOKEN_S) + comb = CSS_COMBINATOR_ANCESTOR; + else + break; + + parserutils_vector_iterate(vector, ctx); + + /* If we've seen a '+' or '>', we're done. */ + if (comb != CSS_COMBINATOR_ANCESTOR) + break; + } - if (tokenIsChar(token, '+')) - *result = CSS_COMBINATOR_SIBLING; - else if (tokenIsChar(token, '>')) - *result = CSS_COMBINATOR_PARENT; - else if (token->type == CSS_TOKEN_S) - *result = CSS_COMBINATOR_ANCESTOR; - else + /* No valid combinator found */ + if (comb == CSS_COMBINATOR_NONE) return CSS_INVALID; + /* Consume any trailing whitespace */ consumeWhitespace(vector, ctx); + *result = comb; + return CSS_OK; } @@ -793,6 +805,18 @@ css_error parseSelector(css_css21 *c, const parserutils_vector *vector, if (error != CSS_OK) return error; + /* In the case of "html , body { ... }", the whitespace after + * "html" and "body" will be considered an ancestor combinator. + * This clearly is not the case, however. Therefore, as a + * special case, if we've got an ancestor combinator and there + * are no further tokens, or if the next token is a comma, + * we ignore the supposed combinator and continue. */ + if (comb == CSS_COMBINATOR_ANCESTOR && + ((token = parserutils_vector_peek(vector, + *ctx)) == NULL || + tokenIsChar(token, ','))) + continue; + error = parseSimpleSelector(c, vector, ctx, &other); if (error != CSS_OK) return error; -- cgit v1.2.3