On 12/11/20 12:11 PM, Henri Verbeet wrote:
On Fri, 11 Dec 2020 at 00:27, Zebediah Figura <zfigura(a)codeweavers.com> wrote:
+struct preproc_location +{ + const char *filename; + unsigned int first_line, first_column; +}; + struct preproc_ctx { void *scanner;
+ struct vkd3d_shader_message_context *message_context; struct vkd3d_string_buffer buffer; + unsigned int line, column; + const char *source_name; + + bool error; };
There seems to be some duplication of location information between struct vkd3d_shader_message_context, struct preproc_ctx, and struct preproc_location. Is that intentional? If it is, would it make sense to introduce e.g. a struct vkd3d_shader_source_location instead of struct preproc_location, and then use that structure in both struct vkd3d_shader_message_context and struct preproc_ctx?
Wrt the vkd3d_shader_message_context part—the current structure definitely isn't a great fit for the preprocessor or HLSL parser (i.e. the parts that use yacc) because the location tracking means that we'll be setting a new location on every error call. (And of course most of the other parsers we have don't really have a meaningful concept of line/column locations...) But I wasn't sure enough to actually try to redesign those parts, and it seemed like something that could be deferred, so I just left it alone... Wrt preproc_location vs preproc_ctx—part of the rub here is that {line, column} is a bit different from {first_line, first_column}; i.e. if we were to add {last_line, last_column}, that wouldn't be a part of preproc_ctx.
+#define YYLLOC_DEFAULT(cur, rhs, n) \ + do \ + { \ + if (n) \ + { \ + (cur).filename = YYRHSLOC(rhs, 1).filename; \ + (cur).first_line = YYRHSLOC(rhs, 1).first_line; \ + (cur).first_column = YYRHSLOC(rhs, 1).first_column; \ + } \ + else \ + { \ + (cur).filename = YYRHSLOC(rhs, 0).filename; \ + (cur).first_line = YYRHSLOC(rhs, 0).first_line; \ + (cur).first_column = YYRHSLOC(rhs, 0).first_column; \ + } \ + } while (0) + Generally speaking, we would try to avoid multi-line macros by doing something like the following where possible:
static inline void preproc_yylloc_default(struct preproc_location *cur, const struct preproc_location *rhs, int n) { if (n) { cur->filename = YYRHSLOC(rhs, 1).filename; cur->first_line = YYRHSLOC(rhs, 1).first_line; cur->first_column = YYRHSLOC(rhs, 1).first_column; } else { cur->filename = YYRHSLOC(rhs, 0).filename; cur->first_line = YYRHSLOC(rhs, 0).first_line; cur->first_column = YYRHSLOC(rhs, 0).first_column; } }
#define YYLLOC_DEFAULT(cur, rhs, n) preproc_yylloc_default(&cur, rhs, n)
In this particular case though, I think all that essentially reduces to:
#define YYLLOC_DEFAULT(cur, rhs, n) (cur) = YYRHSLOC(rhs, !!n)
Excellent point, thanks.