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).
	* 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 5ad90d528d
commit 66381412d9
8 changed files with 207 additions and 94 deletions

View File

@@ -1,3 +1,18 @@
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).
* NEWS (2.5): Add an announcement about named references.
2009-09-17 Akim Demaille <demaille@gostai.com>
doc: fixes.

25
NEWS
View File

@@ -53,6 +53,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",
quotearg_n_style (3, escape_quoting_style, loc.start.file));
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

@@ -410,7 +410,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;
@@ -422,11 +423,11 @@ 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"),
dollar_or_at, var->id, at_spec);
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"),
dollar_or_at, var->id, at_spec);
complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
dollar_or_at, var->id, at_spec);
}
else
{
@@ -441,7 +442,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
@@ -450,7 +451,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
@@ -458,17 +459,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);
}
}
@@ -482,6 +488,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. */
@@ -594,29 +603,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"),
quote (text));
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 =
@@ -626,11 +646,14 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
}
case 2:
default:
complain_at (text_loc, _("ambiguous reference: %s"),
quote (text));
show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, false);
return INVALID_REF;
{
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, indent + SUB_INDENT);
return INVALID_REF;
}
}
/* Not reachable. */

View File

@@ -256,16 +256,16 @@ exp:
AT_BISON_CHECK([-o test.c test.y], 1, [],
[[test.y:50.51-60: invalid reference: `$<ival>lo9'
test.y:50.3-68: symbol not found in production: lo9
test.y:50.3-68: symbol not found in production: lo9
test.y:51.51-60: warning: misleading reference: `$<ival>exp'
test.y:42.1-3: warning: refers to: $exp at $$
test.y:51.7: warning: possibly meant: $x, hiding $exp at $1
test.y:51.41: warning: possibly meant: $r, hiding $exp at $4
test.y:42.1-3: warning: refers to: $exp at $$
test.y:51.7: warning: possibly meant: $x, hiding $exp at $1
test.y:51.41: warning: possibly meant: $r, hiding $exp at $4
test.y:52.51-52: $l of `exp' has no declared type
test.y:55.46-49: invalid reference: `$r12'
test.y:55.3-53: symbol not found in production: r12
test.y:55.3-53: symbol not found in production: r12
test.y:56.29-33: invalid reference: `$expo'
test.y:56.3-46: symbol not found in production: expo
test.y:56.3-46: symbol not found in production: expo
]])
AT_CLEANUP
@@ -281,8 +281,8 @@ foo.bar: '2'
]])
AT_BISON_CHECK([-o test.c test.y], 0, [],
[[test.y:11.22-29: warning: misleading reference: `$foo.bar'
test.y:11.8-10: warning: refers to: $foo at $1
test.y:11.12-18: warning: possibly meant: $[foo.bar] at $2
test.y:11.8-10: warning: refers to: $foo at $1
test.y:11.12-18: warning: possibly meant: $[foo.bar] at $2
]])
AT_CLEANUP
@@ -357,44 +357,44 @@ factor: '(' expr ')' { $$ = $2; }
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
[[test.y:24.36-41: invalid reference: `$cond1'
test.y:23.11-24.62: symbol not found in production: cond1
test.y:23.11-24.62: symbol not found in production: cond1
test.y:26.43-53: invalid reference: `$stmt.field'
test.y:25.11-26.60: symbol not found in production: stmt
test.y:25.35-38: possibly meant: $then.field, hiding $stmt.field at $4
test.y:25.11-26.60: symbol not found in production: stmt
test.y:25.35-38: possibly meant: $then.field, hiding $stmt.field at $4
test.y:28.43-52: invalid reference: `$stmt.list'
test.y:27.11-28.59: symbol not found in production: stmt
test.y:27.30-38: possibly meant: $[stmt.list] at $4
test.y:27.11-28.59: symbol not found in production: stmt
test.y:27.30-38: possibly meant: $[stmt.list] at $4
test.y:30.43-46: ambiguous reference: `$xyz'
test.y:29.35-37: refers to: $xyz at $4
test.y:29.50-52: refers to: $xyz at $6
test.y:29.35-37: refers to: $xyz at $4
test.y:29.50-52: refers to: $xyz at $6
test.y:32.43-52: invalid reference: `$stmt.list'
test.y:31.11-32.63: symbol not found in production: stmt
test.y:31.40-43: possibly meant: $then, hiding $[stmt.list] at $4
test.y:31.61-64: possibly meant: $else, hiding $[stmt.list] at $6
test.y:31.11-32.63: symbol not found in production: stmt
test.y:31.40-43: possibly meant: $then, hiding $[stmt.list] at $4
test.y:31.61-64: possibly meant: $else, hiding $[stmt.list] at $6
test.y:34.43-58: invalid reference: `$stmt.list.field'
test.y:33.11-34.69: symbol not found in production: stmt
test.y:33.40-43: possibly meant: $then.field, hiding $[stmt.list].field at $4
test.y:33.61-64: possibly meant: $else.field, hiding $[stmt.list].field at $6
test.y:33.11-34.69: symbol not found in production: stmt
test.y:33.40-43: possibly meant: $then.field, hiding $[stmt.list].field at $4
test.y:33.61-64: possibly meant: $else.field, hiding $[stmt.list].field at $6
test.y:36.43-54: invalid reference: `$[stmt.list]'
test.y:35.11-36.71: symbol not found in production: stmt.list
test.y:35.40-43: possibly meant: $then, hiding $[stmt.list] at $4
test.y:35.61-64: possibly meant: $else, hiding $[stmt.list] at $6
test.y:35.11-36.71: symbol not found in production: stmt.list
test.y:35.40-43: possibly meant: $then, hiding $[stmt.list] at $4
test.y:35.61-64: possibly meant: $else, hiding $[stmt.list] at $6
test.y:38.43-49: invalid reference: `$then.1'
test.y:37.11-38.60: symbol not found in production: then
test.y:37.40-45: possibly meant: $[then.1] at $4
test.y:37.11-38.60: symbol not found in production: then
test.y:37.40-45: possibly meant: $[then.1] at $4
test.y:40.43-55: invalid reference: `$then.1.field'
test.y:39.11-40.66: symbol not found in production: then
test.y:39.40-45: possibly meant: $[then.1].field at $4
test.y:39.11-40.66: symbol not found in production: then
test.y:39.40-45: possibly meant: $[then.1].field at $4
test.y:42.44-50: invalid reference: `$stmt.x'
test.y:41.12-42.57: symbol not found in production: stmt
test.y:41.36-41: possibly meant: $[stmt.x].x, hiding $stmt.x at $4
test.y:41.36-41: possibly meant: $[stmt.x] at $4
test.y:41.12-42.57: symbol not found in production: stmt
test.y:41.36-41: possibly meant: $[stmt.x].x, hiding $stmt.x at $4
test.y:41.36-41: possibly meant: $[stmt.x] at $4
test.y:44.13-22: invalid reference: `$if-stmt-a'
test.y:43.12-44.59: symbol not found in production: if
test.y:43.1-9: possibly meant: $[if-stmt-a] at $$
test.y:43.12-44.59: symbol not found in production: if
test.y:43.1-9: possibly meant: $[if-stmt-a] at $$
test.y:46.46-54: invalid reference: `$then-a.f'
test.y:45.12-46.65: symbol not found in production: then
test.y:45.41-46: possibly meant: $[then-a].f at $4
test.y:45.12-46.65: symbol not found in production: then
test.y:45.41-46: possibly meant: $[then-a].f at $4
]])
AT_CLEANUP
@@ -528,36 +528,36 @@ sym_b : 'b';
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
[[test.y:13.8-17: invalid reference: `$sym.field'
test.y:12.1-13.21: symbol not found in production: sym
test.y:12.1-13.21: symbol not found in production: sym
test.y:16.8-21: invalid reference: `$<aa>sym.field'
test.y:15.1-16.25: symbol not found in production: sym
test.y:15.1-16.25: symbol not found in production: sym
test.y:19.8-19: invalid reference: `$[sym.field]'
test.y:18.1-19.23: symbol not found in production: sym.field
test.y:18.1-19.23: symbol not found in production: sym.field
test.y:22.8-23: invalid reference: `$<aa>[sym.field]'
test.y:21.1-22.27: symbol not found in production: sym.field
test.y:21.1-22.27: symbol not found in production: sym.field
test.y:25.8-11: invalid reference: `$sym'
test.y:24.1-25.15: symbol not found in production: sym
test.y:24.1-25.15: symbol not found in production: sym
test.y:28.8-15: invalid reference: `$<aa>sym'
test.y:27.1-28.19: symbol not found in production: sym
test.y:27.1-28.19: symbol not found in production: sym
test.y:31.8-13: invalid reference: `$[sym]'
test.y:30.1-33.21: symbol not found in production before $3: sym
test.y:30.1-33.21: symbol not found in production before $3: sym
test.y:33.8-17: invalid reference: `$<aa>[sym]'
test.y:30.1-33.21: symbol not found in production: sym
test.y:30.1-33.21: symbol not found in production: sym
test.y:37.8-17: invalid reference: `$sym-field'
test.y:36.1-37.21: symbol not found in production: sym
test.y:36.1-37.21: symbol not found in production: sym
test.y:40.8-21: invalid reference: `$<aa>sym-field'
test.y:39.1-40.25: symbol not found in production: sym
test.y:39.1-40.25: symbol not found in production: sym
test.y:43.8-19: invalid reference: `$[sym-field]'
test.y:42.1-43.23: symbol not found in production: sym-field
test.y:42.1-43.23: symbol not found in production: sym-field
test.y:46.8-23: invalid reference: `$<aa>[sym-field]'
test.y:45.1-46.27: symbol not found in production: sym-field
test.y:45.1-46.27: symbol not found in production: sym-field
test.y:49.8-11: invalid reference: `$sym'
test.y:48.1-49.15: symbol not found in production: sym
test.y:48.1-49.15: symbol not found in production: sym
test.y:52.8-15: invalid reference: `$<aa>sym'
test.y:51.1-52.19: symbol not found in production: sym
test.y:51.1-52.19: symbol not found in production: sym
test.y:55.8-13: invalid reference: `$[sym]'
test.y:54.1-57.21: symbol not found in production before $3: sym
test.y:54.1-57.21: symbol not found in production before $3: sym
test.y:57.8-17: invalid reference: `$<aa>[sym]'
test.y:54.1-57.21: symbol not found in production: sym
test.y:54.1-57.21: symbol not found in production: sym
]])
AT_CLEANUP