Hi Frank, > Le 20 avr. 2020 à 23:02, Frank Heckenbach <f.heckenb...@fh-soft.de> a écrit : > > Akim Demaille wrote:
>> So you are in a way "in between": not using the Autotools magic, >> but willing to use the machinery inside. >> >> I'm saying it's wrong. > > Not saying, I guess!? ;) Of course, sorry about that :) I'm installing this, I think it should make things much clearer. Thanks a lot for the impetus! Comments most welcome. commit 3237a3c107339de21d75ff6b3b130cc72b04aaff Author: Akim Demaille <akim.demai...@gmail.com> Date: Sun Apr 19 09:13:47 2020 +0200 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. 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