Keep sub-messages aligned. Fix strings for translation.

* src/location.h: (location_print): Add return value.
	* src/location.c: (location_print): Return number of printed
	characters.
	* src/complain.h: Two new functions (complain_at_indent,
	warn_at_indent).
	* src/complain.cpp: Implement the alignment mechanism. Add new
	static variable (indent_ptr). Use and update it (error_message,
	complain_at_indent, warn_at_indent).
	* src/scan-code.l: Fix strings for translations. Use new *_indent
	functions (parse_ref, show_sub_messages).
	* tests/named-ref.at: Adjust testcases.
	* NEWS (2.5): Add an announcement about named references.
This commit is contained in:
Alex Rozenman
2009-09-19 12:59:33 +03:00
parent d93b5f50cf
commit 348f560883
8 changed files with 208 additions and 94 deletions

View File

@@ -1,3 +1,19 @@
2009-09-19 Alex Rozenman <rozenman@gmail.com>
Keep sub-messages aligned. Fix strings for translation.
* src/location.h: (location_print): Add return value.
* src/location.c: (location_print): Return number of printed
characters.
* src/complain.h: Two new functions (complain_at_indent,
warn_at_indent).
* src/complain.cpp: Implement the alignment mechanism. Add new
static variable (indent_ptr). Use and update it (error_message,
complain_at_indent, warn_at_indent).
* src/scan-code.l: Fix strings for translations. Use new *_indent
functions (parse_ref, show_sub_messages).
* tests/named-ref.at: Adjust testcases.
* NEWS (2.5): Add an announcement about named references.
2009-09-13 Joel E. Denny <jdenny@clemson.edu>
tests: clean up push.at test group titles.

25
NEWS
View File

@@ -3,6 +3,31 @@ Bison News
* Changes in version 2.5 (????-??-??):
** Named References Support
Historically, Yacc and Bison have supported positional references
($n, $$) to allow access to symbol values from inside of semantic
actions code.
Starting from this version, Bison can also accept named references.
When no ambiguity is possible, original symbol names may be used
as named references:
if_stmt : 'if' cond_expr 'then' then_stmt ';'
{ $if_stmt = mk_if_stmt($cond_expr, $then_stmt); }
In the more common case, explicit names may be declared:
stmt[res] : 'if' expr[cond] 'then' stmt[then] 'else' stmt[else] ';'
{ $res = mk_if_stmt($cond, $then, $else); }
Location information is also accessible using @name syntax. When
accessing symbol names containing dots or dashes, explicit bracketing
($[sym.1]) must be used.
These features are experimental in this version. More user feedback
will help to stabilize them.
** IELR(1) and Canonical LR(1) Support
IELR(1) is a minimal LR(1) parser table generation algorithm. That

View File

@@ -29,6 +29,7 @@
#include "getargs.h"
bool complaint_issued;
static unsigned *indent_ptr = 0;
@@ -46,11 +47,22 @@ error_message (location *loc,
const char *prefix,
const char *message, va_list args)
{
unsigned pos = 0;
if (loc)
location_print (stderr, *loc);
pos += location_print (stderr, *loc);
else
fputs (current_file ? current_file : program_name, stderr);
fputs (": ", stderr);
pos += fprintf(stderr, "%s", current_file ? current_file : program_name);
pos += fprintf(stderr, ": ");
if (indent_ptr)
{
if (!*indent_ptr)
*indent_ptr = pos;
else if (*indent_ptr > pos)
fprintf (stderr, "%*s", *indent_ptr - pos, "");
indent_ptr = 0;
}
if (prefix)
fprintf (stderr, "%s: ", prefix);
@@ -93,6 +105,15 @@ warn_at (location loc, const char *message, ...)
ERROR_MESSAGE (&loc, _("warning"), message);
}
void
warn_at_indent (location loc, unsigned *indent,
const char *message, ...)
{
set_warning_issued ();
indent_ptr = indent;
ERROR_MESSAGE (&loc, _("warning"), message);
}
void
warn (const char *message, ...)
{
@@ -112,6 +133,15 @@ complain_at (location loc, const char *message, ...)
complaint_issued = true;
}
void
complain_at_indent (location loc, unsigned *indent,
const char *message, ...)
{
indent_ptr = indent;
ERROR_MESSAGE (&loc, NULL, message);
complaint_issued = true;
}
void
complain (const char *message, ...)
{

View File

@@ -31,6 +31,13 @@ void warn (char const *format, ...)
void warn_at (location loc, char const *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
/* Generate a message aligned by an indent.
When *indent == 0, assign message's indent to *indent,
When *indent > 0, align the message by *indent value. */
void warn_at_indent (location loc, unsigned *indent,
char const *format, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
/** An error, but we continue and die later. */
void complain (char const *format, ...)
@@ -39,6 +46,13 @@ void complain (char const *format, ...)
void complain_at (location loc, char const *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
/* Generate a message aligned by an indent.
When *indent == 0, assign message's indent to *indent,
When *indent > 0, align the message by *indent value. */
void complain_at_indent (location loc, unsigned *indent,
char const *format, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
/** An incompatibility with POSIX Yacc: mapped either to warn* or
complain* depending on yacc_flag. */

View File

@@ -98,40 +98,44 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
/* Output to OUT the location LOC.
Warning: it uses quotearg's slot 3. */
void
unsigned
location_print (FILE *out, location loc)
{
unsigned res = 0;
int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
fprintf (out, "%s",
res += fprintf (out, "%s",
quotearg_n_style (3, escape_quoting_style, loc.start.file));
if (0 <= loc.start.line)
{
fprintf(out, ":%d", loc.start.line);
res += fprintf(out, ":%d", loc.start.line);
if (0 <= loc.start.column)
fprintf (out, ".%d", loc.start.column);
res += fprintf (out, ".%d", loc.start.column);
}
if (loc.start.file != loc.end.file)
{
fprintf (out, "-%s",
quotearg_n_style (3, escape_quoting_style, loc.end.file));
res += fprintf (out, "-%s",
quotearg_n_style (3, escape_quoting_style,
loc.end.file));
if (0 <= loc.end.line)
{
fprintf(out, ":%d", loc.end.line);
res += fprintf(out, ":%d", loc.end.line);
if (0 <= end_col)
fprintf (out, ".%d", end_col);
res += fprintf (out, ".%d", end_col);
}
}
else if (0 <= loc.end.line)
{
if (loc.start.line < loc.end.line)
{
fprintf (out, "-%d", loc.end.line);
res += fprintf (out, "-%d", loc.end.line);
if (0 <= end_col)
fprintf (out, ".%d", end_col);
res += fprintf (out, ".%d", end_col);
}
else if (0 <= end_col && loc.start.column < end_col)
fprintf (out, "-%d", end_col);
res += fprintf (out, "-%d", end_col);
}
return res;
}
void

View File

@@ -98,7 +98,9 @@ extern location const empty_location;
void location_compute (location *loc,
boundary *cur, char const *token, size_t size);
void location_print (FILE *out, location loc);
/* Print location to file. Return number of actually printed
characters. */
unsigned location_print (FILE *out, location loc);
/* Return -1, 0, 1, depending whether a is before, equal, or
after b. */

View File

@@ -409,7 +409,8 @@ get_at_spec(unsigned symbol_index)
static void
show_sub_messages (const char* cp, bool explicit_bracketing,
int midrule_rhs_index, char dollar_or_at, bool is_warning)
int midrule_rhs_index, char dollar_or_at,
bool is_warning, unsigned indent)
{
unsigned i;
@@ -421,10 +422,10 @@ show_sub_messages (const char* cp, bool explicit_bracketing,
if (var->err == 0)
{
if (is_warning)
warn_at (var->loc, _(" refers to: %c%s at %s"),
warn_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
dollar_or_at, var->id, at_spec);
else
complain_at (var->loc, _(" refers to: %c%s at %s"),
complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
dollar_or_at, var->id, at_spec);
}
else
@@ -440,7 +441,7 @@ show_sub_messages (const char* cp, bool explicit_bracketing,
/* Create the explanation message. */
obstack_init (&msg_buf);
obstack_fgrow1 (&msg_buf, " possibly meant: %c", dollar_or_at);
obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
if (contains_dot_or_dash (id))
obstack_fgrow1 (&msg_buf, "[%s]", id);
else
@@ -449,7 +450,7 @@ show_sub_messages (const char* cp, bool explicit_bracketing,
if (var->err & VARIANT_HIDDEN)
{
obstack_fgrow1 (&msg_buf, ", hiding %c", dollar_or_at);
obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
if (contains_dot_or_dash (var->id))
obstack_fgrow1 (&msg_buf, "[%s]", var->id);
else
@@ -457,17 +458,22 @@ show_sub_messages (const char* cp, bool explicit_bracketing,
obstack_sgrow (&msg_buf, tail);
}
obstack_fgrow1 (&msg_buf, " at %s", at_spec);
obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
obstack_fgrow1 (&msg_buf, ", cannot be accessed from "
"mid-rule action at $%d", midrule_rhs_index);
{
const char *format =
_(", cannot be accessed from mid-rule action at $%d");
obstack_fgrow1 (&msg_buf, format, midrule_rhs_index);
}
obstack_1grow (&msg_buf, '\0');
if (is_warning)
warn_at (id_loc, _("%s"), (char *) obstack_finish (&msg_buf));
warn_at_indent (id_loc, &indent, "%s",
(char *) obstack_finish (&msg_buf));
else
complain_at (id_loc, _("%s"), (char *) obstack_finish (&msg_buf));
complain_at_indent (id_loc, &indent, "%s",
(char *) obstack_finish (&msg_buf));
obstack_free (&msg_buf, 0);
}
}
@@ -481,6 +487,9 @@ show_sub_messages (const char* cp, bool explicit_bracketing,
points to LHS ($$) of the current rule or midrule. */
#define LHS_REF (INT_MIN + 1)
/* Sub-messages indent. */
#define SUB_INDENT (4)
/* Parse named or positional reference. In case of positional
references, can return negative values for $-n "deep" stack
accesses. */
@@ -593,29 +602,40 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
{
unsigned len = (explicit_bracketing || !ref_tail_fields) ?
cp_end - cp : ref_tail_fields - cp;
const char *message = "symbol not found in production";
unsigned indent = 0;
complain_at (text_loc, _("invalid reference: %s"), quote (text));
complain_at_indent (text_loc, &indent, _("invalid reference: %s"),
quote (text));
indent += SUB_INDENT;
if (midrule_rhs_index)
complain_at (rule->location, _(" %s before $%d: %.*s"),
message, midrule_rhs_index, len, cp);
{
const char *format =
_("symbol not found in production before $%d: %.*s");
complain_at_indent (rule->location, &indent, format,
midrule_rhs_index, len, cp);
}
else
complain_at (rule->location, _(" %s: %.*s"),
message, len, cp);
{
const char *format =
_("symbol not found in production: %.*s");
complain_at_indent (rule->location, &indent, format,
len, cp);
}
if (variant_count > 0)
show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, false);
dollar_or_at, false, indent);
return INVALID_REF;
}
case 1:
{
unsigned indent = 0;
if (variant_count > 1)
{
warn_at (text_loc, _("misleading reference: %s"),
warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
quote (text));
show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, true);
dollar_or_at, true, indent + SUB_INDENT);
}
{
unsigned symbol_index =
@@ -625,12 +645,15 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
}
case 2:
default:
complain_at (text_loc, _("ambiguous reference: %s"),
{
unsigned indent = 0;
complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
quote (text));
show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, false);
dollar_or_at, false, indent + SUB_INDENT);
return INVALID_REF;
}
}
/* Not reachable. */
return INVALID_REF;