diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2015-05-19 17:14:28 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2015-05-19 17:22:53 +0200 |
commit | 02cc7931ef0f04218bd50b3e0e396a6dcb009962 (patch) | |
tree | 0c286621e1498561d23bdc543e1852ea88deaf63 | |
parent | 0dc2cbf8fedd5615898b09314d0c899c6e911baa (diff) | |
download | mupdf-02cc7931ef0f04218bd50b3e0e396a6dcb009962.tar.xz |
epub: Parse CSS combinators left-associatively.
Fixes bug 695994 where multiple child selectors would not match properly.
The "a > b > c" rule should be interpreted as ((a > b) > c) in order
to match properly.
-rw-r--r-- | source/html/css-parse.c | 67 |
1 files changed, 27 insertions, 40 deletions
diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 0946043e..f9d7595c 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -776,55 +776,42 @@ static fz_css_selector *parse_simple_selector(struct lexbuf *buf) fz_css_error(buf, "expected selector"); } -static fz_css_selector *parse_combinator(struct lexbuf *buf, fz_css_selector *a) +static fz_css_selector *parse_combinator(struct lexbuf *buf, int c, fz_css_selector *a) { - fz_css_selector *s, *b; - if (accept(buf, '+')) - { - white(buf); - b = parse_selector(buf); - s = fz_new_css_selector(buf->ctx, NULL); - s->combine = '+'; - s->left = a; - s->right = b; - return s; - } - if (accept(buf, '>')) - { - white(buf); - b = parse_selector(buf); - s = fz_new_css_selector(buf->ctx, NULL); - s->combine = '>'; - s->left = a; - s->right = b; - return s; - } - return a; + fz_css_selector *sel, *b; + white(buf); + b = parse_simple_selector(buf); + sel = fz_new_css_selector(buf->ctx, NULL); + sel->combine = c; + sel->left = a; + sel->right = b; + return sel; } static fz_css_selector *parse_selector(struct lexbuf *buf) { - fz_css_selector *s, *a, *b; - - a = parse_simple_selector(buf); - if (accept(buf, ' ')) + fz_css_selector *sel = parse_simple_selector(buf); + for (;;) { - s = parse_combinator(buf, a); - if (s == a && buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF) + if (accept(buf, ' ')) { - b = parse_selector(buf); - s = fz_new_css_selector(buf->ctx, NULL); - s->combine = ' '; - s->left = a; - s->right = b; - return s; + if (accept(buf, '+')) + sel = parse_combinator(buf, '+', sel); + else if (accept(buf, '>')) + sel = parse_combinator(buf, '>', sel); + else if (buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF) + sel = parse_combinator(buf, ' ', sel); + else + break; } + else if (accept(buf, '+')) + sel = parse_combinator(buf, '+', sel); + else if (accept(buf, '>')) + sel = parse_combinator(buf, '>', sel); + else + break; } - else - { - s = parse_combinator(buf, a); - } - return s; + return sel; } static fz_css_selector *parse_selector_list(struct lexbuf *buf) |