bug-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bison-Announce] Bison 3.5.90 released [beta]


From: Akim Demaille
Subject: Re: [Bison-Announce] Bison 3.5.90 released [beta]
Date: Fri, 24 Apr 2020 19:01:35 +0200

Hi Frank,

> Le 20 avr. 2020 à 23:02, Frank Heckenbach <address@hidden> 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 <address@hidden>
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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]