+static void
+matrix_expr_location__ (const struct matrix_expr *e,
+ const struct msg_location **minp,
+ const struct msg_location **maxp)
+{
+ struct msg_location *loc = e->location;
+ if (loc)
+ {
+ if (loc->p[0].line
+ && (!minp
+ || loc->p[0].line < (*minp)->p[0].line
+ || (loc->p[0].line == (*minp)->p[0].line
+ && loc->p[0].column < (*minp)->p[0].column)))
+ *minp = loc;
+
+ if (loc->p[1].line
+ && (!maxp
+ || loc->p[1].line > (*maxp)->p[1].line
+ || (loc->p[1].line == (*maxp)->p[1].line
+ && loc->p[1].column > (*maxp)->p[1].column)))
+ *maxp = loc;
+ return;
+ }
+
+ assert (e->op != MOP_NUMBER && e->op != MOP_VARIABLE && e->op != MOP_EOF);
+ for (size_t i = 0; i < e->n_subs; i++)
+ matrix_expr_location__ (e->subs[i], minp, maxp);
+}
+
+static struct msg_location *
+matrix_expr_location (const struct matrix_expr *e_)
+{
+ struct matrix_expr *e = CONST_CAST (struct matrix_expr *, e_);
+
+ if (!e->location)
+ {
+ const struct msg_location *min = NULL;
+ const struct msg_location *max = NULL;
+ matrix_expr_location__ (e, &min, &max);
+ if (min && max)
+ {
+ e->location = msg_location_dup (min);
+ e->location->p[1] = max->p[1];
+ }
+ }
+
+ return e->location;
+}
+
+static struct matrix_expr *
+matrix_expr_wrap_location (struct matrix_state *s, int start_ofs,
+ struct matrix_expr *e)
+{
+ if (e && !e->location)
+ e->location = lex_ofs_location (s->lexer, start_ofs,
+ lex_ofs (s->lexer) - 1);
+ return e;
+}
+