mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-23 11:13:03 +00:00
examples: bistromathic: demonstrate internationalization
Currently it was only using stubs. Let's actually translate the strings using gettext. * examples/c/bistromathic/local.mk: Define LOCALEDIR, BISON_LOCALEDIR and link with libintl. * examples/c/bistromathic/parse.y: Use them. Remove useless includes. Take ENABLE_NLS into account. (error_format_string): New. (yyreport_syntax_error): Rewrite to rely on a format string, which is more appropriate for internationalization. * examples/c/bistromathic/Makefile: We no longer use Flex. We need readline and intl. * doc/bison.texi: Point to bistromathic for a better option for internationalization. * po/POTFILES.in: Add bistromathic.
This commit is contained in:
@@ -7514,7 +7514,9 @@ values, which is always less than @code{YYNTOKENS}.
|
|||||||
The name of the symbol whose kind is @var{symbol}, possibly translated.
|
The name of the symbol whose kind is @var{symbol}, possibly translated.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
A custom syntax error function looks as follows.
|
A custom syntax error function looks as follows. This implementation is
|
||||||
|
inappropriate for internationalization, see the @file{c/bistromathic}
|
||||||
|
example for a better altnative.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
int
|
int
|
||||||
@@ -10601,7 +10603,7 @@ Print the version number of Bison and exit.
|
|||||||
Print the name of the directory containing locale-dependent data.
|
Print the name of the directory containing locale-dependent data.
|
||||||
|
|
||||||
@item --print-datadir
|
@item --print-datadir
|
||||||
Print the name of the directory containing skeletons and XSLT.
|
Print the name of the directory containing skeletons, CSS and XSLT.
|
||||||
|
|
||||||
@item -u
|
@item -u
|
||||||
@item --update
|
@item --update
|
||||||
@@ -12074,7 +12076,9 @@ values, which is always less than @code{YYNTOKENS}.
|
|||||||
The name of the symbol whose kind is @var{symbol}, possibly translated.
|
The name of the symbol whose kind is @var{symbol}, possibly translated.
|
||||||
@end deftypemethod
|
@end deftypemethod
|
||||||
|
|
||||||
A custom syntax error function looks as follows.
|
A custom syntax error function looks as follows. This implementation is
|
||||||
|
inappropriate for internationalization, see the @file{c/bistromathic}
|
||||||
|
example for a better altnative.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
void
|
void
|
||||||
@@ -13327,6 +13331,10 @@ public void reportSyntaxError(YYParser.Context ctx) @{
|
|||||||
System.err.println("");
|
System.err.println("");
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
This implementation is inappropriate for internationalization, see the
|
||||||
|
@file{c/bistromathic} example for a better altnative.
|
||||||
@end deftypemethod
|
@end deftypemethod
|
||||||
|
|
||||||
@node Java Action Features
|
@node Java Action Features
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ This example demonstrates best practices when using Bison.
|
|||||||
push-parser API to feed the parser with the incoming tokens.
|
push-parser API to feed the parser with the incoming tokens.
|
||||||
- It features an interactive command line with completion based on the
|
- It features an interactive command line with completion based on the
|
||||||
parser state, based on `yyexpected_tokens`.
|
parser state, based on `yyexpected_tokens`.
|
||||||
|
- It uses Bison's standard catalogue for internationalization of generated
|
||||||
|
messages.
|
||||||
- It uses a custom syntax error with location, lookahead correction and
|
- It uses a custom syntax error with location, lookahead correction and
|
||||||
token internationalization.
|
token internationalization.
|
||||||
- It supports debug traces with semantic values.
|
- It supports debug traces with semantic values.
|
||||||
|
|||||||
@@ -3,20 +3,26 @@
|
|||||||
|
|
||||||
BASE = bistromathic
|
BASE = bistromathic
|
||||||
BISON = bison
|
BISON = bison
|
||||||
FLEX = flex
|
|
||||||
XSLTPROC = xsltproc
|
XSLTPROC = xsltproc
|
||||||
|
|
||||||
|
# We need to find the headers and libs for readline and intl.
|
||||||
|
# You probably need to customize this for your own environment.
|
||||||
|
CPPFLAGS = -I/opt/local/include
|
||||||
|
LDFLAGS = -L/opt/local/lib
|
||||||
|
|
||||||
|
# Find the translation catalogue for Bison's generated messagess.
|
||||||
|
BISON_LOCALEDIR = $(shell $(BISON) $(BISON_FLAGS) --print-localedir)
|
||||||
|
CPPFLAGS += -DENABLE_NLS -DBISON_LOCALEDIR='"$(BISON_LOCALEDIR)"'
|
||||||
|
|
||||||
|
LIBS = -lreadline -lintl
|
||||||
|
|
||||||
all: $(BASE)
|
all: $(BASE)
|
||||||
|
|
||||||
%.c %.h %.xml %.gv: %.y
|
%.c %.h %.xml %.gv: %.y
|
||||||
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
|
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
|
||||||
|
|
||||||
%.c: %.l
|
$(BASE): parse.o
|
||||||
$(FLEX) $(FLEXFLAGS) -o$*.c $<
|
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
scan.o: parse.h
|
|
||||||
$(BASE): parse.o scan.o
|
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
run: $(BASE)
|
run: $(BASE)
|
||||||
@echo "Type bistromathic expressions. Quit with ctrl-d."
|
@echo "Type bistromathic expressions. Quit with ctrl-d."
|
||||||
@@ -28,8 +34,7 @@ html: $(BASE).html
|
|||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
$(BASE) *.o \
|
$(BASE) *.o \
|
||||||
parse.[ch] parse.output parse.xml parse.html parse.gv \
|
parse.[ch] parse.output parse.xml parse.html parse.gv
|
||||||
scan.c
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(CLEANFILES)
|
rm -f $(CLEANFILES)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ This example demonstrates best practices when using Bison.
|
|||||||
push-parser API to feed the parser with the incoming tokens.
|
push-parser API to feed the parser with the incoming tokens.
|
||||||
- It features an interactive command line with completion based on the
|
- It features an interactive command line with completion based on the
|
||||||
parser state, based on `yyexpected_tokens`.
|
parser state, based on `yyexpected_tokens`.
|
||||||
|
- It uses Bison's standard catalogue for internationalization of generated
|
||||||
|
messages.
|
||||||
- It uses a custom syntax error with location, lookahead correction and
|
- It uses a custom syntax error with location, lookahead correction and
|
||||||
token internationalization.
|
token internationalization.
|
||||||
- It supports debug traces with semantic values.
|
- It supports debug traces with semantic values.
|
||||||
|
|||||||
@@ -26,8 +26,11 @@ nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h
|
|||||||
%D%/parse.c: $(dependencies)
|
%D%/parse.c: $(dependencies)
|
||||||
|
|
||||||
# Don't use gnulib's system headers.
|
# Don't use gnulib's system headers.
|
||||||
%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
|
%C%_bistromathic_CPPFLAGS = \
|
||||||
%C%_bistromathic_LDADD = -lm -lreadline
|
-DBISON_LOCALEDIR='"$(localdir)"' \
|
||||||
|
-DLOCALEDIR='"$(localdir)"' \
|
||||||
|
-I$(top_srcdir)/%D% -I$(top_builddir)/%D%
|
||||||
|
%C%_bistromathic_LDADD = -lm -lreadline $(LIBINTL)
|
||||||
|
|
||||||
dist_bistromathic_DATA = %D%/parse.y %D%/Makefile %D%/README.md
|
dist_bistromathic_DATA = %D%/parse.y %D%/Makefile %D%/README.md
|
||||||
CLEANFILES += %D%/parse.[ch] %D%/parse.output
|
CLEANFILES += %D%/parse.[ch] %D%/parse.output
|
||||||
|
|||||||
@@ -3,13 +3,23 @@
|
|||||||
%code top {
|
%code top {
|
||||||
#include <ctype.h> // isdigit
|
#include <ctype.h> // isdigit
|
||||||
#include <math.h> // cos, sin, etc.
|
#include <math.h> // cos, sin, etc.
|
||||||
#include <stddef.h> // ptrdiff_t
|
|
||||||
#include <stdio.h> // printf
|
#include <stdio.h> // printf
|
||||||
#include <stdlib.h> // calloc.
|
#include <stdlib.h> // calloc
|
||||||
#include <string.h> // strcmp
|
#include <string.h> // strcmp
|
||||||
|
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
|
||||||
|
#if defined ENABLE_NLS && ENABLE_NLS
|
||||||
|
// Unable the translation of Bison's generated messages.
|
||||||
|
# define YYENABLE_NLS 1
|
||||||
|
# include <libintl.h>
|
||||||
|
// Unless specified otherwise, we expect bistromathic's own
|
||||||
|
// catalogue to be installed in the same tree as Bison's catalogue.
|
||||||
|
# ifndef LOCALEDIR
|
||||||
|
# define LOCALEDIR BISON_LOCALEDIR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
%code requires {
|
%code requires {
|
||||||
@@ -40,8 +50,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
%code {
|
%code {
|
||||||
#define N_
|
#if defined ENABLE_NLS && ENABLE_NLS
|
||||||
#define _
|
# define _(Msgid) gettext (Msgid)
|
||||||
|
#else
|
||||||
|
# define _(Msgid) (Msgid)
|
||||||
|
#endif
|
||||||
|
#define N_(Msgid) (Msgid)
|
||||||
|
|
||||||
// Whether to quit.
|
// Whether to quit.
|
||||||
int done = 0;
|
int done = 0;
|
||||||
@@ -286,35 +300,69 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
|||||||
| Parser. |
|
| Parser. |
|
||||||
`---------*/
|
`---------*/
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
error_format_string (int argc)
|
||||||
|
{
|
||||||
|
switch (argc)
|
||||||
|
{
|
||||||
|
default: /* Avoid compiler warnings. */
|
||||||
|
case 0: return _("%@: syntax error");
|
||||||
|
case 1: return _("%@: syntax error: unexpected %u");
|
||||||
|
case 2: return _("%@: syntax error: expected %0e before %u");
|
||||||
|
case 3: return _("%@: syntax error: expected %0e or %1e before %u");
|
||||||
|
case 4: return _("%@: syntax error: expected %0e or %1e or %2e before %u");
|
||||||
|
case 5: return _("%@: syntax error: expected %0e or %1e or %2e or %3e before %u");
|
||||||
|
case 6: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e before %u");
|
||||||
|
case 7: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e before %u");
|
||||||
|
case 8: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e or %6e before %u");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
yyreport_syntax_error (const yypcontext_t *ctx)
|
yyreport_syntax_error (const yypcontext_t *ctx)
|
||||||
{
|
{
|
||||||
int res = 0;
|
enum { ARGS_MAX = 7 };
|
||||||
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
|
yysymbol_kind_t arg[ARGS_MAX];
|
||||||
fprintf (stderr, ": syntax error");
|
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
|
||||||
// Report the tokens expected at this point.
|
if (argsize < 0)
|
||||||
{
|
return argsize;
|
||||||
enum { TOKENMAX = 10 };
|
const char *format = error_format_string (1 + argsize);
|
||||||
yysymbol_kind_t expected[TOKENMAX];
|
|
||||||
int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX);
|
while (*format)
|
||||||
if (n < 0)
|
// %@: location.
|
||||||
// Forward errors to yyparse.
|
if (format[0] == '%' && format[1] == '@')
|
||||||
res = n;
|
{
|
||||||
|
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
|
||||||
|
format += 2;
|
||||||
|
}
|
||||||
|
// %t: unexpected token.
|
||||||
|
else if (format[0] == '%' && format[1] == 'u')
|
||||||
|
{
|
||||||
|
fputs (yysymbol_name (yypcontext_token (ctx)), stderr);
|
||||||
|
format += 2;
|
||||||
|
}
|
||||||
|
// %0e, %1e...: expected token.
|
||||||
|
else if (format[0] == '%'
|
||||||
|
&& isdigit (format[1])
|
||||||
|
&& format[2] == 'e'
|
||||||
|
&& (format[1] - '0') < argsize)
|
||||||
|
{
|
||||||
|
int i = format[1] - '0';
|
||||||
|
fputs (yysymbol_name (arg[i]), stderr);
|
||||||
|
format += 3;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
for (int i = 0; i < n; ++i)
|
{
|
||||||
fprintf (stderr, "%s %s",
|
fputc (*format, stderr);
|
||||||
i == 0 ? ": expected" : " or", yysymbol_name (expected[i]));
|
++format;
|
||||||
}
|
}
|
||||||
// Report the unexpected token.
|
fputc ('\n', stderr);
|
||||||
{
|
return 0;
|
||||||
yysymbol_kind_t lookahead = yypcontext_token (ctx);
|
|
||||||
if (lookahead != YYSYMBOL_YYEMPTY)
|
|
||||||
fprintf (stderr, " before %s", yysymbol_name (lookahead));
|
|
||||||
}
|
|
||||||
fprintf (stderr, "\n");
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called by yyparse on error.
|
// Called by yyparse on error.
|
||||||
void yyerror (YYLTYPE *loc, char const *msg)
|
void yyerror (YYLTYPE *loc, char const *msg)
|
||||||
{
|
{
|
||||||
@@ -467,6 +515,18 @@ void init_readline (void)
|
|||||||
|
|
||||||
int main (int argc, char const* argv[])
|
int main (int argc, char const* argv[])
|
||||||
{
|
{
|
||||||
|
#if defined ENABLE_NLS && ENABLE_NLS
|
||||||
|
// Set up internationalization.
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
// Use Bison's standard translation catalogue for error messages
|
||||||
|
// (the generated messages).
|
||||||
|
bindtextdomain ("bison-runtime", BISON_LOCALEDIR);
|
||||||
|
// The translation catalogue of bistromathic is actually included in
|
||||||
|
// Bison's. In your own project, use the name of your project.
|
||||||
|
bindtextdomain ("bison", LOCALEDIR);
|
||||||
|
textdomain ("bison");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Enable parse traces on option -p.
|
// Enable parse traces on option -p.
|
||||||
if (argc == 2 && strcmp (argv[1], "-p") == 0)
|
if (argc == 2 && strcmp (argv[1], "-p") == 0)
|
||||||
yydebug = 1;
|
yydebug = 1;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
examples/c/bistromathic/parse.y
|
||||||
src/complain.c
|
src/complain.c
|
||||||
src/conflicts.c
|
src/conflicts.c
|
||||||
src/files.c
|
src/files.c
|
||||||
|
|||||||
Reference in New Issue
Block a user