summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Neves <lcneves@gmail.com>2017-09-17 23:56:00 -0400
committerLucas Neves <lcneves@gmail.com>2017-09-25 22:01:56 -0400
commitdf4542814b4d217f31768d007b7fb513dc9c46ac (patch)
tree64cb6cc6e45b06ced59450382bd678dd5af45aff
parent45a06a36bc19baf6e93e6ff2c8b1fe72b208f225 (diff)
downloadlibcss-df4542814b4d217f31768d007b7fb513dc9c46ac.tar.gz
Parse: rewrite flex shorthand parser to comply with standards
Parse: rewrite flex shorthand parser to conform to standards
-rw-r--r--src/parse/properties/flex.c357
-rw-r--r--test/data/select/tests1.dat120
2 files changed, 250 insertions, 227 deletions
diff --git a/src/parse/properties/flex.c b/src/parse/properties/flex.c
index f189b3b..dfec5bf 100644
--- a/src/parse/properties/flex.c
+++ b/src/parse/properties/flex.c
@@ -28,62 +28,21 @@
* If the input is invalid, then \a *ctx remains unchanged.
*/
-css_error flex_grow_helper(const css_token *token, css_fixed *number);
-css_error flex_basis_helper(css_language *c,
- const parserutils_vector *vector, int *ctx,
- css_fixed *basis_length, uint32_t *basis_unit,
- opcode_t *basis_op);
-
-
-css_error flex_basis_helper(css_language *c,
- const parserutils_vector *vector, int *ctx,
- css_fixed *basis_length, uint32_t *basis_unit,
- opcode_t *basis_op)
-{
- css_error error;
- error = css__parse_unit_specifier(c, vector, ctx,
- UNIT_PX, basis_length, basis_unit);
-
- if (error == CSS_OK) {
- if (*basis_unit & UNIT_ANGLE ||
- *basis_unit & UNIT_TIME ||
- *basis_unit & UNIT_FREQ) {
- return CSS_INVALID;
- }
- *basis_op = FLEX_BASIS_SET;
- }
-
- return error;
-}
-
-css_error flex_grow_helper(const css_token *token, css_fixed *number)
-{
- if (token->type != CSS_TOKEN_NUMBER)
- return CSS_INVALID;
-
- size_t consumed = 0;
- css_fixed num = css__number_from_lwc_string(
- token->idata, false, &consumed);
-
- /* Invalid if there are trailing characters */
- if (consumed != lwc_string_length(token->idata))
- return CSS_INVALID;
-
- /* Invalid if number is negative */
- if (num < 0)
- return CSS_INVALID;
-
- *number = num;
- return CSS_OK;
-}
-
css_error css__parse_flex(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style *result)
{
int orig_ctx = *ctx;
+ int prev_ctx;
const css_token *token;
css_error error;
+ bool grow = true;
+ bool shrink = true;
+ bool basis = true;
+ css_style *grow_style;
+ css_style *shrink_style;
+ css_style *basis_style;
+ bool match;
/* Firstly, handle inherit */
token = parserutils_vector_peek(vector, *ctx);
@@ -92,16 +51,16 @@ css_error css__parse_flex(css_language *c,
if (is_css_inherit(c, token)) {
error = css_stylesheet_style_inherit(result,
- CSS_PROP_FLEX_GROW);
+ CSS_PROP_FLEX_SHRINK);
if (error != CSS_OK)
return error;
error = css_stylesheet_style_inherit(result,
- CSS_PROP_FLEX_SHRINK);
+ CSS_PROP_FLEX_GROW);
+
if (error != CSS_OK)
return error;
-
error = css_stylesheet_style_inherit(result,
CSS_PROP_FLEX_BASIS);
@@ -109,149 +68,9 @@ css_error css__parse_flex(css_language *c,
parserutils_vector_iterate(vector, ctx);
return error;
- }
-
- /* Default values */
- opcode_t grow_op = FLEX_GROW_SET;
- css_fixed grow_number = 0;
- opcode_t shrink_op = FLEX_SHRINK_SET;
- css_fixed shrink_number = INTTOFIX(1);
- opcode_t basis_op = FLEX_BASIS_AUTO;
- css_fixed basis_length = 0;
- uint32_t basis_unit = UNIT_PX;
-
- /* Attempt to parse the various longhand properties */
- *ctx = orig_ctx;
- size_t length = -1;
-
- do {
- ++length;
- token = parserutils_vector_iterate(vector, ctx);
- } while (token != NULL);
-
- *ctx = orig_ctx;
-
- switch (length) {
- case 1:
- token = parserutils_vector_iterate(vector, ctx);
- if (token == NULL || token->type != CSS_TOKEN_IDENT) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
-
- /*
- * Handle auto and none
- * auto = flex: 1 1 auto;
- * none = flex: 0 0 auto;
- */
- bool match;
- if ((lwc_string_caseless_isequal(
- token->idata, c->strings[AUTO],
- &match) == lwc_error_ok && match) ||
- (lwc_string_caseless_isequal(
- token->idata, c->strings[NONE],
- &match) == lwc_error_ok && match)) {
- if ((lwc_string_caseless_isequal(
- token->idata, c->strings[AUTO],
- &match) == lwc_error_ok && match)) {
- grow_number = INTTOFIX(1);
- }
- else {
- shrink_number = 0;
- }
-
- }
-
- /* Token must be either flex-basis or flex-grow */
- else {
- *ctx = orig_ctx;
- error = flex_basis_helper(c, vector, ctx,
- &basis_length, &basis_unit,
- &basis_op);
-
- if (error != CSS_OK) {
- /* Positive number: equivalent of
- * flex: <positive number> 1 0; */
- *ctx = orig_ctx;
- token = parserutils_vector_iterate(vector, ctx);
- error = flex_grow_helper(
- token, &grow_number);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
- basis_op = FLEX_BASIS_SET;
- }
- }
- break;
-
- case 2:
- /* First value must be flex-grow */
- token = parserutils_vector_iterate(vector, ctx);
- error = flex_grow_helper(
- token, &grow_number);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
-
- /* Second value must be either flex-basis or flex-shrink */
- int prev_ctx = *ctx;
- error = flex_basis_helper(c, vector, ctx,
- &basis_length, &basis_unit, &basis_op);
-
- if (error != CSS_OK) {
- /* Two positive numbers: equivalent of
- * flex: <number_1> <number_2> 0; */
- *ctx = prev_ctx;
- token = parserutils_vector_iterate(vector, ctx);
- error = flex_grow_helper(
- token, &shrink_number);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
- basis_op = FLEX_BASIS_SET;
- }
- break;
-
- case 3:
- /* First value must be flex-grow */
- token = parserutils_vector_iterate(vector, ctx);
- error = flex_grow_helper(
- token, &grow_number);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
-
- /* Second value must be flex-shrink */
- token = parserutils_vector_iterate(vector, ctx);
- error = flex_grow_helper(
- token, &shrink_number);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
-
- /* Third value must be flex-basis */
- error = flex_basis_helper(c, vector, ctx,
- &basis_length, &basis_unit, &basis_op);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
- break;
-
- default:
- return CSS_INVALID;
}
-
+
/* allocate styles */
- css_style *grow_style;
- css_style *shrink_style;
- css_style *basis_style;
-
error = css__stylesheet_style_create(c->sheet, &grow_style);
if (error != CSS_OK)
return error;
@@ -260,59 +79,155 @@ css_error css__parse_flex(css_language *c,
if (error != CSS_OK) {
css__stylesheet_style_destroy(grow_style);
return error;
- }
+ }
error = css__stylesheet_style_create(c->sheet, &basis_style);
if (error != CSS_OK) {
- css__stylesheet_style_destroy(shrink_style);
css__stylesheet_style_destroy(grow_style);
+ css__stylesheet_style_destroy(shrink_style);
return error;
}
- error = css__stylesheet_style_appendOPV(grow_style,
- CSS_PROP_FLEX_GROW, 0, grow_op);
- if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ /* Handle none, equivalent of flex: 0 0 auto; */
+ if ((token->type == CSS_TOKEN_IDENT) &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[NONE],
+ &match) == lwc_error_ok && match)) {
+ error = css__stylesheet_style_appendOPV(grow_style,
+ CSS_PROP_FLEX_GROW, 0, FLEX_GROW_SET);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
- error = css__stylesheet_style_append(grow_style, grow_number);
- if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ error = css__stylesheet_style_append(grow_style, 0);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
- error = css__stylesheet_style_appendOPV(shrink_style,
- CSS_PROP_FLEX_SHRINK, 0, shrink_op);
- if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ error = css__stylesheet_style_appendOPV(shrink_style,
+ CSS_PROP_FLEX_SHRINK, 0, FLEX_SHRINK_SET);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
- error = css__stylesheet_style_append(shrink_style, shrink_number);
- if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ error = css__stylesheet_style_append(shrink_style, 0);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
- error = css__stylesheet_style_appendOPV(basis_style,
- CSS_PROP_FLEX_BASIS, 0, basis_op);
- if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ error = css__stylesheet_style_appendOPV(basis_style,
+ CSS_PROP_FLEX_BASIS, 0, FLEX_BASIS_AUTO);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ grow = shrink = basis = false;
+ parserutils_vector_iterate(vector, ctx);
+ }
+
+ /* Handle auto, equivalent of flex: 1 1 auto; */
+ else if ((token->type == CSS_TOKEN_IDENT) &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[AUTO],
+ &match) == lwc_error_ok && match)) {
+ error = css__stylesheet_style_appendOPV(grow_style,
+ CSS_PROP_FLEX_GROW, 0, FLEX_GROW_SET);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ error = css__stylesheet_style_append(grow_style, INTTOFIX(1));
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ error = css__stylesheet_style_appendOPV(shrink_style,
+ CSS_PROP_FLEX_SHRINK, 0, FLEX_SHRINK_SET);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ error = css__stylesheet_style_append(shrink_style, INTTOFIX(1));
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ error = css__stylesheet_style_appendOPV(basis_style,
+ CSS_PROP_FLEX_BASIS, 0, FLEX_BASIS_AUTO);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ grow = shrink = basis = false;
+ parserutils_vector_iterate(vector, ctx);
+ }
+
+ /* Attempt to parse the various longhand properties */
+ else do {
+ prev_ctx = *ctx;
+ error = CSS_OK;
+
+ /* Ensure that we're not about to parse another inherit */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token != NULL && is_css_inherit(c, token)) {
+ error = CSS_INVALID;
+ goto css__parse_flex_cleanup;
+ }
- if (basis_op == (opcode_t) FLEX_BASIS_SET) {
- error = css__stylesheet_style_append(basis_style, basis_length);
+ if ((grow) &&
+ (error = css__parse_flex_grow(c, vector,
+ ctx, grow_style)) == CSS_OK) {
+ grow = false;
+ } else if ((basis) &&
+ (error = css__parse_flex_basis(c, vector,
+ ctx, basis_style)) == CSS_OK) {
+ basis = false;
+ } else if ((shrink) &&
+ (error = css__parse_flex_shrink(c, vector,
+ ctx, shrink_style)) == CSS_OK) {
+ shrink = false;
+ }
+
+ if (error == CSS_OK) {
+ consumeWhitespace(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ } else {
+ /* Forcibly cause loop to exit */
+ token = NULL;
+ }
+ } while (*ctx != prev_ctx && token != NULL);
+
+ /* defaults */
+ if (grow) {
+ error = css__stylesheet_style_appendOPV(grow_style,
+ CSS_PROP_FLEX_GROW, 0, FLEX_GROW_SET);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ error = css__stylesheet_style_append(grow_style, 0);
if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ goto css__parse_flex_cleanup;
+ }
+
+ if (shrink) {
+ error = css__stylesheet_style_appendOPV(shrink_style,
+ CSS_PROP_FLEX_SHRINK, 0, FLEX_SHRINK_SET);
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+
+ error = css__stylesheet_style_append(shrink_style, INTTOFIX(1));
+ if (error != CSS_OK)
+ goto css__parse_flex_cleanup;
+ }
- error = css__stylesheet_style_append(basis_style, basis_unit);
+ if (basis) {
+ error = css__stylesheet_style_appendOPV(basis_style,
+ CSS_PROP_FLEX_BASIS, 0, FLEX_BASIS_AUTO);
if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ goto css__parse_flex_cleanup;
}
error = css__stylesheet_merge_style(result, grow_style);
if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ goto css__parse_flex_cleanup;
error = css__stylesheet_merge_style(result, shrink_style);
if (error != CSS_OK)
- goto css__parse_flex_flow_cleanup;
+ goto css__parse_flex_cleanup;
error = css__stylesheet_merge_style(result, basis_style);
-css__parse_flex_flow_cleanup:
+css__parse_flex_cleanup:
css__stylesheet_style_destroy(basis_style);
css__stylesheet_style_destroy(shrink_style);
diff --git a/test/data/select/tests1.dat b/test/data/select/tests1.dat
index 2d30083..a8b527d 100644
--- a/test/data/select/tests1.dat
+++ b/test/data/select/tests1.dat
@@ -6940,6 +6940,116 @@ word-spacing: normal
writing-mode: horizontal-tb
z-index: auto
#reset
+#
+#tree
+| div*
+#ua
+div { flex: 2 3 10px; }
+#user
+#errors
+#expected:
+align-content: stretch
+align-items: stretch
+align-self: auto
+background-attachment: scroll
+background-color: #00000000
+background-image: none
+background-position: 0% 0%
+background-repeat: repeat
+border-collapse: separate
+border-spacing: 0px 0px
+border-top-color: #ff000000
+border-right-color: #ff000000
+border-bottom-color: #ff000000
+border-left-color: #ff000000
+border-top-style: none
+border-right-style: none
+border-bottom-style: none
+border-left-style: none
+border-top-width: 2px
+border-right-width: 2px
+border-bottom-width: 2px
+border-left-width: 2px
+bottom: auto
+box-sizing: content-box
+break-after: auto
+break-before: auto
+break-inside: auto
+caption-side: top
+clear: none
+clip: auto
+color: #ff000000
+column-count: auto
+column-fill: balance
+column-gap: normal
+column-rule-color: #ff000000
+column-rule-style: none
+column-rule-width: 2px
+column-span: none
+column-width: auto
+content: normal
+counter-increment: none
+counter-reset: none
+cursor: auto
+direction: ltr
+display: inline
+empty-cells: show
+flex-basis: 10px
+flex-direction: row
+flex-grow: 2.000
+flex-shrink: 3.000
+flex-wrap: nowrap
+float: none
+font-family: sans-serif
+font-size: 12pt
+font-style: normal
+font-variant: normal
+font-weight: normal
+height: auto
+justify-content: flex-start
+left: auto
+letter-spacing: normal
+line-height: normal
+list-style-image: none
+list-style-position: outside
+list-style-type: disc
+margin-top: 0px
+margin-right: 0px
+margin-bottom: 0px
+margin-left: 0px
+max-height: none
+max-width: none
+min-height: 0px
+min-width: 0px
+opacity: 1.000
+order: 0
+outline-color: invert
+outline-style: none
+outline-width: 2px
+overflow-x: visible
+overflow-y: visible
+padding-top: 0px
+padding-right: 0px
+padding-bottom: 0px
+padding-left: 0px
+position: static
+quotes: none
+right: auto
+table-layout: auto
+text-align: default
+text-decoration: none
+text-indent: 0px
+text-transform: none
+top: auto
+unicode-bidi: normal
+vertical-align: baseline
+visibility: visible
+white-space: normal
+width: auto
+word-spacing: normal
+writing-mode: horizontal-tb
+z-index: auto
+#reset
#tree
| div*
@@ -7214,7 +7324,7 @@ cursor: auto
direction: ltr
display: inline
empty-cells: show
-flex-basis: 0px
+flex-basis: auto
flex-direction: row
flex-grow: 0.000
flex-shrink: 1.000
@@ -7495,9 +7605,7 @@ z-index: auto
#tree
| div*
#ua
-div { }
-#user
-div { }
+div { flex: 2 3em; }
#errors
#expected:
align-content: stretch
@@ -7546,9 +7654,9 @@ cursor: auto
direction: ltr
display: inline
empty-cells: show
-flex-basis: auto
+flex-basis: 3em
flex-direction: row
-flex-grow: 0.000
+flex-grow: 2.000
flex-shrink: 1.000
flex-wrap: nowrap
float: none