From e7022323796ca8b7e0674be8ece9bb0cc22cc976 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 3 Oct 2020 21:08:21 +0100 Subject: parse: Tests and fixes for calc() parser. Co-authored-by: Michael Drake --- src/bytecode/bytecode.h | 13 ++-- src/parse/properties/utils.c | 71 ++++++++++++-------- test/data/parse2/calc.dat | 152 ++++++++++++++++++++++++++++++++++++++++++- test/dump.h | 7 ++ 4 files changed, 209 insertions(+), 34 deletions(-) diff --git a/src/bytecode/bytecode.h b/src/bytecode/bytecode.h index be163b1..70c8b01 100644 --- a/src/bytecode/bytecode.h +++ b/src/bytecode/bytecode.h @@ -24,12 +24,13 @@ enum flag { }; enum calc_opcodes { - CALC_PUSH_VALUE = 'V', - CALC_ADD = '+', - CALC_SUBTRACT = '-', - CALC_MULTIPLY = '*', - CALC_DIVIDE = '/', - CALC_FINISH = '=', + CALC_PUSH_NUMBER = 'N', + CALC_PUSH_VALUE = 'V', + CALC_ADD = '+', + CALC_SUBTRACT = '-', + CALC_MULTIPLY = '*', + CALC_DIVIDE = '/', + CALC_FINISH = '=', }; typedef enum unit { diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index 7f9d9d2..fe5ee6b 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -1364,6 +1364,31 @@ css__parse_calc_sum(css_language *c, const parserutils_vector *vector, int *ctx, css_style *result); +static css_error +css__parse_calc_number( + const parserutils_vector *vector, int *ctx, + css_style *result) +{ + const css_token *token; + css_fixed num; + size_t consumed; + + /* Consume the number token */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || token->type != CSS_TOKEN_NUMBER) { + return CSS_INVALID; + } + + num = css__number_from_string((const uint8_t *)lwc_string_data(token->idata), + lwc_string_length(token->idata), false, &consumed); + + if (consumed != lwc_string_length(token->idata)) { + return CSS_INVALID; + } + + return css__stylesheet_style_vappend(result, 2, (css_code_t) CALC_PUSH_NUMBER, (css_code_t)num); +} + static css_error css__parse_calc_value(css_language *c, const parserutils_vector *vector, int *ctx, @@ -1377,6 +1402,7 @@ css__parse_calc_value(css_language *c, token = parserutils_vector_peek(vector, *ctx); if (tokenIsChar(token, '(')) { parserutils_vector_iterate(vector, ctx); + consumeWhitespace(vector, ctx); error = css__parse_calc_sum(c, vector, ctx, result); if (error != CSS_OK) { return error; @@ -1389,7 +1415,12 @@ css__parse_calc_value(css_language *c, /* Consume the close-paren to complete this value */ parserutils_vector_iterate(vector, ctx); } else switch (token->type) { - case CSS_TOKEN_NUMBER: /* Fall through */ + case CSS_TOKEN_NUMBER: + error = css__parse_calc_number(vector, ctx, result); + if (error != CSS_OK) { + return error; + } + break; case CSS_TOKEN_DIMENSION: /* Fall through */ case CSS_TOKEN_PERCENTAGE: { @@ -1412,11 +1443,7 @@ css__parse_calc_value(css_language *c, break; } - token = parserutils_vector_peek(vector, *ctx); - while (token->type == CSS_TOKEN_S) { - parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); - } + consumeWhitespace(vector, ctx); return error; } @@ -1462,14 +1489,15 @@ css__parse_calc_product(css_language *c, } /* Consume that * or / now */ parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); - while (token->type == CSS_TOKEN_S) { - parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); + consumeWhitespace(vector, ctx); + + if (multiplication) { + /* parse another value */ + error = css__parse_calc_value(c, vector, ctx, result); + } else { + error = css__parse_calc_number(vector, ctx, result); } - /* parse another value */ - error = css__parse_calc_value(c, vector, ctx, result); if (error != CSS_OK) break; @@ -1516,12 +1544,7 @@ css__parse_calc_sum(css_language *c, } /* Consume that + or - now */ parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); - - while (token->type == CSS_TOKEN_S) { - parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); - } + consumeWhitespace(vector, ctx); /* parse another product */ error = css__parse_calc_product(c, vector, ctx, result); @@ -1547,17 +1570,14 @@ css_error css__parse_calc(css_language *c, css_error error = CSS_OK; css_style *calc_style = NULL; + consumeWhitespace(vector, ctx); + token = parserutils_vector_peek(vector, *ctx); if (token == NULL) { *ctx = orig_ctx; return CSS_INVALID; } - while (token->type == CSS_TOKEN_S) { - parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); - } - error = css__stylesheet_style_create(c->sheet, &calc_style); if (error != CSS_OK) goto cleanup; @@ -1574,11 +1594,8 @@ css_error css__parse_calc(css_language *c, if (error != CSS_OK) goto cleanup; + consumeWhitespace(vector, ctx); token = parserutils_vector_peek(vector, *ctx); - while (token->type == CSS_TOKEN_S) { - parserutils_vector_iterate(vector, ctx); - token = parserutils_vector_peek(vector, *ctx); - } if (!tokenIsChar(token, ')')) { /* If we don't get a close-paren, give up now */ error = CSS_INVALID; diff --git a/test/data/parse2/calc.dat b/test/data/parse2/calc.dat index 95abf6c..e9d176d 100644 --- a/test/data/parse2/calc.dat +++ b/test/data/parse2/calc.dat @@ -4,4 +4,154 @@ #expected | * | height: /* -> 0px */ calc(50vh 10px + =) -#reset \ No newline at end of file +#reset + +#data +* { line-height: calc(50vh + 10px)} +#errors +#expected +| * +| line-height: /* -> 0any */ calc(50vh 10px + =) +#reset + +#data +* { line-height: calc( / 2)} +#errors +#expected +| * +#reset + +#data +* { line-height: calc( + 2)} +#errors +#expected +| * +#reset + +#data +* { line-height: calc(2 / 2px)} +#errors +#expected +| * +#reset + +#data +* { z-index: calc(50vh + 10px)} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(50vh 10px + =) +#reset + +#data +* { z-index: calc(2 * 3)} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(2 3 * =) +#reset + +#data +* { z-index: calc(50vh + 10px / 9)} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(50vh 10px 9 / + =) +#reset + +#data +* { z-index: calc(1 + 2 + 3 + 4)} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(1 2 + 3 + 4 + =) +#reset + +#data +* { z-index: calc(1 + 2 * 3 + 4)} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(1 2 3 * + 4 + =) +#reset + +#data +* { z-index: calc((1 + 2) * (3 + 4))} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(1 2 + 3 4 + * =) +#reset + +#data +* { z-index: calc(1 + 2} +#errors +#expected +| * +#reset + +#data +* { z-index: calc(} +#errors +#expected +| * +#reset + +#data +* { z-index: calc} +#errors +#expected +| * +#reset + +#data +* { z-index: calc (1 + 2)} +#errors +#expected +| * +#reset + +#data +* { z-index: calc(1)} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(1 =) +#reset + +#data +* { z-index: calc()} +#errors +#expected +| * +#reset + +#data +* { z-index: calc((1 + 2)} +#errors +#expected +| * +#reset + +#data +* { z-index: calc(((1 + 2)))} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(1 2 + =) +#reset + +#data +* { z-index: calc( ( ( 1 + 2 ) ) )} +#errors +#expected +| * +| z-index: /* -> 0number */ calc(1 2 + =) +#reset + +#data +* { z-index: calc( ( 3 / ( 1 + 2 ) ) )} +#errors +#expected +| * +#reset diff --git a/test/dump.h b/test/dump.h index 852de84..f320e67 100644 --- a/test/dump.h +++ b/test/dump.h @@ -825,6 +825,13 @@ void dump_bytecode(css_style *style, char **ptr, uint32_t depth) dump_unit(num, unit, ptr); *ptr += sprintf(*ptr, " "); break; + case CALC_PUSH_NUMBER: { + css_fixed num = *((css_fixed *)bytecode); + ADVANCE(sizeof(num)); + dump_number(num, ptr); + *ptr += sprintf(*ptr, " "); + break; + } } default: *ptr += sprintf(*ptr, "??%d ", calc_opcode); -- cgit v1.2.3