summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-04-19 09:13:47 +0200
committerAkim Demaille <akim.demaille@gmail.com>2020-04-24 19:03:12 +0200
commitb42702d738bff79b16d96b102166dd19d27760a9 (patch)
tree0d0d66d7e098c536bc4e777e472485d486ed7572
parent401e7c5c36af9b09154c9af8c6e0626923529cbd (diff)
downloadbison-b42702d738bff79b16d96b102166dd19d27760a9.tar.gz
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.
-rw-r--r--doc/bison.texi14
-rw-r--r--examples/c/README.md2
-rw-r--r--examples/c/bistromathic/Makefile23
-rw-r--r--examples/c/bistromathic/README.md2
-rw-r--r--examples/c/bistromathic/local.mk7
-rw-r--r--examples/c/bistromathic/parse.y114
-rw-r--r--po/POTFILES.in1
7 files changed, 122 insertions, 41 deletions
diff --git a/doc/bison.texi b/doc/bison.texi
index 3ed36098..141fcb0c 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -7514,7 +7514,9 @@ values, which is always less than @code{YYNTOKENS}.
The name of the symbol whose kind is @var{symbol}, possibly translated.
@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
int
@@ -10601,7 +10603,7 @@ Print the version number of Bison and exit.
Print the name of the directory containing locale-dependent data.
@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 --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.
@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
void
@@ -13327,6 +13331,10 @@ public void reportSyntaxError(YYParser.Context ctx) @{
System.err.println("");
@}
@end example
+
+@noindent
+This implementation is inappropriate for internationalization, see the
+@file{c/bistromathic} example for a better altnative.
@end deftypemethod
@node Java Action Features
diff --git a/examples/c/README.md b/examples/c/README.md
index e1e04d84..47963f13 100644
--- a/examples/c/README.md
+++ b/examples/c/README.md
@@ -57,6 +57,8 @@ This example demonstrates best practices when using Bison.
push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the
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
token internationalization.
- It supports debug traces with semantic values.
diff --git a/examples/c/bistromathic/Makefile b/examples/c/bistromathic/Makefile
index 359d0ac5..c1ac6887 100644
--- a/examples/c/bistromathic/Makefile
+++ b/examples/c/bistromathic/Makefile
@@ -3,20 +3,26 @@
BASE = bistromathic
BISON = bison
-FLEX = flex
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)
%.c %.h %.xml %.gv: %.y
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
-%.c: %.l
- $(FLEX) $(FLEXFLAGS) -o$*.c $<
-
-scan.o: parse.h
-$(BASE): parse.o scan.o
- $(CC) $(CFLAGS) -o $@ $^
+$(BASE): parse.o
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
run: $(BASE)
@echo "Type bistromathic expressions. Quit with ctrl-d."
@@ -28,8 +34,7 @@ html: $(BASE).html
CLEANFILES = \
$(BASE) *.o \
- parse.[ch] parse.output parse.xml parse.html parse.gv \
- scan.c
+ parse.[ch] parse.output parse.xml parse.html parse.gv
clean:
rm -f $(CLEANFILES)
diff --git a/examples/c/bistromathic/README.md b/examples/c/bistromathic/README.md
index 6b376b71..6b6521de 100644
--- a/examples/c/bistromathic/README.md
+++ b/examples/c/bistromathic/README.md
@@ -6,6 +6,8 @@ This example demonstrates best practices when using Bison.
push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the
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
token internationalization.
- It supports debug traces with semantic values.
diff --git a/examples/c/bistromathic/local.mk b/examples/c/bistromathic/local.mk
index cab026e2..607fdc52 100644
--- a/examples/c/bistromathic/local.mk
+++ b/examples/c/bistromathic/local.mk
@@ -26,8 +26,11 @@ nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h
%D%/parse.c: $(dependencies)
# Don't use gnulib's system headers.
-%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
-%C%_bistromathic_LDADD = -lm -lreadline
+%C%_bistromathic_CPPFLAGS = \
+ -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
CLEANFILES += %D%/parse.[ch] %D%/parse.output
diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y
index a3b34c38..1342ba60 100644
--- a/examples/c/bistromathic/parse.y
+++ b/examples/c/bistromathic/parse.y
@@ -3,13 +3,23 @@
%code top {
#include <ctype.h> // isdigit
#include <math.h> // cos, sin, etc.
- #include <stddef.h> // ptrdiff_t
#include <stdio.h> // printf
- #include <stdlib.h> // calloc.
+ #include <stdlib.h> // calloc
#include <string.h> // strcmp
#include <readline/readline.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 {
@@ -40,8 +50,12 @@
}
%code {
-#define N_
-#define _
+ #if defined ENABLE_NLS && ENABLE_NLS
+ # define _(Msgid) gettext (Msgid)
+ #else
+ # define _(Msgid) (Msgid)
+ #endif
+ #define N_(Msgid) (Msgid)
// Whether to quit.
int done = 0;
@@ -286,35 +300,69 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
| 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
yyreport_syntax_error (const yypcontext_t *ctx)
{
- int res = 0;
- YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
- fprintf (stderr, ": syntax error");
- // Report the tokens expected at this point.
- {
- enum { TOKENMAX = 10 };
- yysymbol_kind_t expected[TOKENMAX];
- int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX);
- if (n < 0)
- // Forward errors to yyparse.
- res = n;
+ enum { ARGS_MAX = 7 };
+ yysymbol_kind_t arg[ARGS_MAX];
+ int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
+ if (argsize < 0)
+ return argsize;
+ const char *format = error_format_string (1 + argsize);
+
+ while (*format)
+ // %@: location.
+ if (format[0] == '%' && format[1] == '@')
+ {
+ 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
- for (int i = 0; i < n; ++i)
- fprintf (stderr, "%s %s",
- i == 0 ? ": expected" : " or", yysymbol_name (expected[i]));
- }
- // Report the unexpected token.
- {
- yysymbol_kind_t lookahead = yypcontext_token (ctx);
- if (lookahead != YYSYMBOL_YYEMPTY)
- fprintf (stderr, " before %s", yysymbol_name (lookahead));
- }
- fprintf (stderr, "\n");
- return res;
+ {
+ fputc (*format, stderr);
+ ++format;
+ }
+ fputc ('\n', stderr);
+ return 0;
}
+
// Called by yyparse on error.
void yyerror (YYLTYPE *loc, char const *msg)
{
@@ -467,6 +515,18 @@ void init_readline (void)
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.
if (argc == 2 && strcmp (argv[1], "-p") == 0)
yydebug = 1;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0961eca3..1eca4cdd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
+examples/c/bistromathic/parse.y
src/complain.c
src/conflicts.c
src/files.c