X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fexpressions%2Fparse.c;h=5277648cef3f75f5558ebef96a861948dde3a99d;hb=e582516e80e5a04f10a651515a35b616911cf4d6;hp=ea3b06a5dbd18ce5fa8394aad8d1c83c2801e9a3;hpb=e1ca4ab566c6f8317ba8ff0fd27046b82b4acd63;p=pspp-builds.git diff --git a/src/expressions/parse.c b/src/expressions/parse.c index ea3b06a5..5277648c 100644 --- a/src/expressions/parse.c +++ b/src/expressions/parse.c @@ -56,6 +56,8 @@ static struct expression *finish_expression (union any_node *, struct expression *); static bool type_check (struct expression *, union any_node **, enum expr_type expected_type); +static union any_node *allocate_unary_variable (struct expression *, + struct variable *); /* Public functions. */ @@ -267,13 +269,12 @@ type_check (struct expression *e, /* Considers whether *NODE may be coerced to type REQUIRED_TYPE. Returns true if possible, false if disallowed. - If DO_COERCION is zero, then *NODE is not modified and there + If DO_COERCION is false, then *NODE is not modified and there are no side effects. - Otherwise, DO_COERCION is nonzero. In this case, we perform - the coercion if possible, possibly modifying *NODE. If the - coercion is not possible then we free *NODE and set *NODE to - a null pointer. + If DO_COERCION is true, we perform the coercion if possible, + modifying *NODE if necessary. If the coercion is not possible + then we free *NODE and set *NODE to a null pointer. This function's interface is somewhat awkward. Use one of the wrapper functions type_coercion(), type_coercion_assert(), or @@ -335,7 +336,8 @@ type_coercion_core (struct expression *e, case OP_ni_format: if ((*node)->type == OP_format - && check_input_specifier (&(*node)->format.f, 0)) + && check_input_specifier (&(*node)->format.f, false) + && check_specifier_type (&(*node)->format.f, NUMERIC, false)) { if (do_coercion) (*node)->type = OP_ni_format; @@ -345,7 +347,8 @@ type_coercion_core (struct expression *e, case OP_no_format: if ((*node)->type == OP_format - && check_output_specifier (&(*node)->format.f, 0)) + && check_output_specifier (&(*node)->format.f, false) + && check_specifier_type (&(*node)->format.f, NUMERIC, false)) { if (do_coercion) (*node)->type = OP_no_format; @@ -387,10 +390,13 @@ type_coercion_core (struct expression *e, } if (do_coercion) - msg (SE, _("Type mismatch while applying %s operator: " - "cannot convert %s to %s."), - operator_name, - atom_type_name (actual_type), atom_type_name (required_type)); + { + msg (SE, _("Type mismatch while applying %s operator: " + "cannot convert %s to %s."), + operator_name, + atom_type_name (actual_type), atom_type_name (required_type)); + *node = NULL; + } return false; } @@ -402,7 +408,7 @@ type_coercion (struct expression *e, atom_type required_type, union any_node **node, const char *operator_name) { - return type_coercion_core (e, required_type, node, operator_name, 1); + return type_coercion_core (e, required_type, node, operator_name, true); } /* Coerces *NODE to type REQUIRED_TYPE. @@ -411,7 +417,7 @@ static void type_coercion_assert (struct expression *e, atom_type required_type, union any_node **node) { - int success = type_coercion_core (e, required_type, node, NULL, 1); + int success = type_coercion_core (e, required_type, node, NULL, true); assert (success); } @@ -421,7 +427,7 @@ static bool is_coercible (atom_type required_type, union any_node *const *node) { return type_coercion_core (NULL, required_type, - (union any_node **) node, NULL, 0); + (union any_node **) node, NULL, false); } /* How to parse an operator. */ @@ -517,7 +523,7 @@ parse_binary_operators (struct expression *e, union any_node *node, /* Convert the left-hand side to type OPERAND_TYPE. */ if (!type_coercion (e, operand_type, &node, operator->name)) - return node; + return NULL; /* Parse the right-hand side and coerce to type OPERAND_TYPE. */ @@ -651,7 +657,7 @@ parse_add (struct expression *e) static const struct operator ops[] = { { '+', OP_ADD, "addition (\"+\")" }, - { '-', OP_SUB, "subtraction (\"-\")-" }, + { '-', OP_SUB, "subtraction (\"-\")" }, }; return parse_binary_operators (e, parse_mul (e), @@ -783,12 +789,7 @@ parse_primary (struct expression *e) /* It looks like a user variable. (It could be a format specifier, but we'll assume it's a variable unless proven otherwise. */ - struct variable *v = parse_dict_variable (e->dict); - assert (v != NULL); - return expr_allocate_unary (e, - (v->type == NUMERIC - ? OP_NUM_VAR : OP_STR_VAR), - expr_allocate_variable (e, v)); + return allocate_unary_variable (e, parse_dict_variable (e->dict)); } else { @@ -803,7 +804,8 @@ parse_primary (struct expression *e) } break; - case T_NUM: + case T_POS_NUM: + case T_NEG_NUM: { union any_node *node = expr_allocate_number (e, tokval); lex_get (); @@ -863,7 +865,7 @@ parse_vector_element (struct expression *e) return expr_allocate_binary (e, (vector->var[0]->type == NUMERIC ? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR), - expr_allocate_vector (e, vector), element); + element, expr_allocate_vector (e, vector)); } /* Individual function parsing. */ @@ -1098,14 +1100,12 @@ no_match (const char *func_name, } else { - ds_create (&s, _("Function invocation ")); + ds_puts (&s, _("Function invocation ")); put_invocation (&s, func_name, args, arg_cnt); ds_puts (&s, _(" does not match any known function. Candidates are:")); for (f = first; f < last; f++) - { - ds_printf (&s, "\n%s", f->prototype); - } + ds_printf (&s, "\n%s", f->prototype); } ds_putc (&s, '.'); @@ -1159,7 +1159,7 @@ parse_function (struct expression *e) goto fail; for (i = 0; i < var_cnt; i++) add_arg (&args, &arg_cnt, &arg_cap, - expr_allocate_variable (e, vars[i])); + allocate_unary_variable (e, vars[i])); free (vars); } else @@ -1422,3 +1422,13 @@ expr_allocate_format (struct expression *e, const struct fmt_spec *format) n->format.f = *format; return n; } + +/* Allocates a unary composite node that represents the value of + variable V in expression E. */ +static union any_node * +allocate_unary_variable (struct expression *e, struct variable *v) +{ + assert (v != NULL); + return expr_allocate_unary (e, v->type == NUMERIC ? OP_NUM_VAR : OP_STR_VAR, + expr_allocate_variable (e, v)); +}