diff options
Diffstat (limited to 'src/html.gram.y')
-rw-r--r-- | src/html.gram.y | 161 |
1 files changed, 105 insertions, 56 deletions
diff --git a/src/html.gram.y b/src/html.gram.y index bce5e93..fae64ff 100644 --- a/src/html.gram.y +++ b/src/html.gram.y @@ -37,4 +37,6 @@ static FILE *tmp_file; static void out_char (int c); static void out_value (pp_value_t *val); +static void deduce_format (pp_value_t *res, + const pp_value_t *a, const pp_value_t *b); %} @@ -84,5 +86,5 @@ eval : IDENT | obrace error cbrace { - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } ; @@ -109,14 +111,14 @@ expr : value if ($1.type == unspecified_value || $3.type == unspecified_value) - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); else if ($1.type != $3.type) { yyerror ("type mismatch in addition"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else { $$.type = $1.type; - $$.prec = maxprec ($1.prec, $3.prec); + deduce_format (&$$, &$1, &$3); switch ($1.type) { @@ -141,19 +143,19 @@ expr : value if ($1.type == unspecified_value || $3.type == unspecified_value) - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); else if ($1.type != $3.type) { yyerror ("type mismatch in subtraction"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else if ($1.type == string_value) { yyerror ("subtraction not defined for strings"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else { $$.type = $1.type; - $$.prec = maxprec ($1.prec, $3.prec); + deduce_format (&$$, &$1, &$3); $$.v.number = $1.v.number - $3.v.number; } @@ -163,19 +165,19 @@ expr : value if ($1.type == unspecified_value || $3.type == unspecified_value) - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); else if ($1.type != $3.type) { yyerror ("type mismatch in multiplication"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else if ($1.type == string_value) { yyerror ("multiplication not defined for strings"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else { $$.type = $1.type; - $$.prec = maxprec ($1.prec, $3.prec); + deduce_format (&$$, &$1, &$3); $$.v.number = $1.v.number * $3.v.number; } @@ -185,24 +187,24 @@ expr : value if ($1.type == unspecified_value || $3.type == unspecified_value) - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); else if ($1.type != $3.type) { yyerror ("type mismatch in division"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else if ($1.type == string_value) { yyerror ("division not defined for strings"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else if (fabs ($3.v.number) < 1.0e-5) { yyerror ("division by zero"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else { $$.type = $1.type; - $$.prec = maxprec ($1.prec, $3.prec); + deduce_format (&$$, &$1, &$3); $$.v.number = $1.v.number / $3.v.number; } @@ -211,14 +213,13 @@ expr : value { if ($2.type == unspecified_value) - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); else if ($2.type == string_value) { yyerror ("unary minus not defined for strings"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else { - $$.type = $2.type; - $$.prec = $2.prec; + $$ = $2; $$.v.number = - $2.v.number; } @@ -227,9 +228,9 @@ expr : value { if ($2.type == unspecified_value) - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); else if ($2.type == string_value) { yyerror ("unary plus not defined for strings"); - $$.type = unspecified_value; + init_value (&$$, unspecified_value, NULL); } else @@ -243,7 +244,7 @@ value : IDENT | NUMBER { - $$.type = numeric_value; - $$.prec = -1; - $$.v.number = $1; + union value v; + v.number = $1; + init_value (&$$, numeric_value, &v); } ; @@ -310,26 +311,58 @@ out_char (int c) static void -out_value (pp_value_t *val) +deduce_format (pp_value_t *res, const pp_value_t *a, const pp_value_t *b) { - switch (val->type) + res->prec = maxprec (a->prec, b->prec); + if (!a->format && b->format) { - case unspecified_value: - fprintf (tmp_file, "#UNSPECIFIED"); - break; + res->fmt = b->fmt; + res->format = b->format; + } + else + { + res->fmt = a->fmt; + res->format = a->format; + } +} - case numeric_value: - if (val->prec >= 0) - fprintf (tmp_file, "%.*f", val->prec, val->v.number); + +void +format_unspecified (FILE *fp, union value v, const char *fmt, int prec) +{ + fprintf (fp, "#UNSPECIFIED"); +} + +void +format_numeric (FILE *fp, union value v, const char *fmt, int prec) +{ + if (prec >= 0) + fprintf (fp, "%.*f", prec, v.number); else - fprintf (tmp_file, "%f", val->v.number); - break; + fprintf (fp, "%f", v.number); +} - case string_value: - if (val->prec > 0) - fprintf (tmp_file, "%.*s", val->prec, val->v.string); +void +format_string (FILE *fp, union value v, const char *fmt, int prec) +{ + if (fmt) + fprintf (fp, fmt, v.string); + else if (prec > 0) + fprintf (fp, "%.*s", prec, v.string); else - fprintf (tmp_file, "%s", val->v.string); - break; + fprintf (fp, "%s", v.string); } + +static value_format_fn default_format[] = { + format_unspecified, + format_numeric, + format_string +}; + +static void +out_value (pp_value_t *val) +{ + value_format_fn format = + val->format ? val->format : default_format[val->type]; + format (tmp_file, val->v, val->fmt, val->prec); } @@ -357,6 +390,25 @@ free_value (pp_value_t *val) } -static void -add_value (pp_tab_t **ptab, const char *name, pp_value_t *val) +void +init_value (pp_value_t *p, value_type type, union value *v) +{ + memset (p, 0, sizeof (*p)); + p->type = type; + p->prec = -1; + switch (p->type) + { + case unspecified_value: + break; + case numeric_value: + p->v.number = v->number; + break; + case string_value: + p->v.string = xstrdup (v->string); + } +} + +static pp_value_t * +add_value (pp_tab_t **ptab, const char *name, + value_type type, union value *v) { pp_tab_t *p; @@ -375,27 +427,24 @@ add_value (pp_tab_t **ptab, const char *name, pp_value_t *val) *ptab = p; } - p->value = *val; + init_value (&p->value, type, v); + return &p->value; } -void +pp_value_t * add_numeric_value (pp_tab_t **ptab, const char *name, double number) { - pp_value_t val; + union value v; - val.type = numeric_value; - val.prec = -1; - val.v.number = number; - add_value (ptab, name, &val); + v.number = number; + return add_value (ptab, name, numeric_value, &v); } -void +pp_value_t * add_string_value (pp_tab_t **ptab, const char *name, const char *string) { - pp_value_t val; + union value v; - val.type = string_value; - val.prec = -1; - val.v.string = xstrdup (string); - add_value (ptab, name, &val); + v.string = xstrdup (string); + return add_value (ptab, name, string_value, &v); } |