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

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.bugs
Message-ID <[email protected]>
Hi Frank!

> Le 18 avr. 2020 à 17:08, Frank Heckenbach <[email protected]> a écrit :
> 
> Akim Demaille wrote:
> 
>> So **please** take the time to play with this beta,
> 
> So far it works well with my parsers.

Great news!  While I have taken care of not breaking backward
compatibility (and in fact the test suite is still using the
old names), s*t happens, so it is reassuring to know that it
works well for you.


>> in particular to
>> see how these features allow you to get rid of dirty hacks you needed
>> to customize your error messages (I listed several such examples in
>> https://lists.gnu.org/r/bison-patches/2020-01/msg00000.html).
> 
> I haven't used any such hacks, but I might start i14ing my parsers

(there were also hacks for people who want to play with quotes
around the token names).

> now that it's properly supported. On that subject:
> 
>>  Therefore, by default, error messages now refer to "end of file"
>>  (internationalized) rather than the cryptic "$end", or to "invaid token"
> 
> Typo: "invaid" (only in NEWS apparently).

Thanks, I've fixed that.


>> **** Token aliases internationalization
>> 
>>  When the %define variable parse.error is set to `custom` or `detailed`,
>>  one may specify which token aliases are to be translated using _().  For
>>  instance
>> 
>>    %token
>>        PLUS   "+"
>>        MINUS  "-"
>>      <double>
>>        NUM _("double precision number")
>>      <symrec*>
>>        FUN _("function")
>>        VAR _("variable")
>> 
>>  In that case the user must define _() and N_(), and yysymbol_name returns
>>  the translated symbol (i.e., it returns '_("variable")' rather that
>>  '"variable"').  In Java, the user must provide an i18n() function.
> 
> I've used GNU gettext, but not those (strange IMHO) macros with it,
> so I had to find out what to define them to. You might want to
> elaborate a bit on that.

So I guess I should point people to the documentation of gettext.
I can elaborate a bit more, but I should not aim at a full description
of how to add i18n, that's way out of scope.

> In examples/c/bistromathic/parse.y I see just:
> 
>  #define N_
>  #define _
> 
> If I do that, I get the compiler warning:
> 
>   error: this condition has identical branches [-Werror=duplicated-branches]
> 
> about:
> 
>    return (yysymbol < YYNTOKENS && yytranslatable[yysymbol]
>            ? _(yy_sname[yysymbol])
>            : yy_sname[yysymbol]);
> 
> Not sure if you consider this a problem, since this seems to be just
> "nop" i14ing.

Yes, that's not the typical set up :)

> Looking further in several tests, I found that apparently "N_"
> (unlike "_") should indeed always be defined as a nop

Yes.  '_' serves two purposes: one is that at runtime it is actually
consulting the translation dictionary to return the translation, the
other is that it is recognized as a markup for strings to
internationalize by the i18n tools that scan the source code.

However in C you can't call a function when you define a table,
so you need to split in two: 'N_' serves as markup, and does nothing,
while '_' actually translates.


> -- but if so,
> can't the skeleton do this by itself?

Hum.

Good point.

I guess it would be ok to just define it if N_ is not yet
#defined.


> Also, since I don't use autoblah,

:) :) :)

> it seems I have to define both
> YYENABLE_NLS and ENABLE_NLS. The former is mentioned in the manual
> (but only in conjunction with autoblah), the latter not at all.
> 
> So if I got it correctly now, this seems to be the minimum required
> for i18n, apart from the bindtextdomain call. Is that correct?
> 
> %define parse.error detailed
> %{
> #define YYENABLE_NLS 1
> #define ENABLE_NLS 1
> #define N_
> static auto _ (const char *s) { return dgettext ("mydomain", s); }
> %}

I don't think this is the right approach.  I think you are trying
to exploit the fact that the skeleton is actually already having
support to translate its own messages ("syntax error, expected...").


Rather I had something like the attachement in mind.  I am very
afraid about really installing this in the source tree, because I
expect tons of portability issues here: the examples are meant to
be self-contained, independent of bison's build, so I cannot use
the same tricks to be portable.

But I agree it would be better to actually demonstrate the whole
process in bistromathic.  I'll see what I can do.

Cheers!

 
commit c993d94c918cdeb60c9d0eb7f8e183697316169c
Author: Akim Demaille <[email protected]>
Date:   Sun Apr 19 09:13:47 2020 +0200

    examples: bistromathic: demontrate internationalization
    
    Currently it was only using stubs.  Let's actually translate the
    strings using gettext.
    
    * examples/c/bistromathic/local.mk: Define LOCALEDIR and link with
    libintl.
    * examples/c/bistromathic/parse.y: Use them.

diff --git a/examples/c/bistromathic/local.mk b/examples/c/bistromathic/local.mk
index cab026e2..f3b9045d 100644
--- a/examples/c/bistromathic/local.mk
+++ b/examples/c/bistromathic/local.mk
@@ -26,8 +26,10 @@ 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 =			\
+  -DLOCALEDIR='"$(localdir)"'			\
+  -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
+%C%_bistromathic_LDADD = -lm -lreadline -lintl
 
 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..a868def9 100644
--- a/examples/c/bistromathic/parse.y
+++ b/examples/c/bistromathic/parse.y
@@ -10,6 +10,10 @@
 
   #include <readline/readline.h>
   #include <readline/history.h>
+
+  #ifdef LOCALEDIR
+  # include <libintl.h>
+  #endif
 }
 
 %code requires {
@@ -40,8 +44,12 @@
 }
 
 %code {
-#define N_
-#define _
+  #ifdef LOCALEDIR
+  # define _(Msgid)  gettext (Msgid)
+  #else
+  # define _(Msgid)  (Msgid)
+  #endif
+  #define N_(Msgid) (Msgid)
 
   // Whether to quit.
   int done = 0;
@@ -467,6 +475,13 @@ void init_readline (void)
 
 int main (int argc, char const* argv[])
 {
+#ifdef LOCALEDIR
+  // Set up internationalization.
+  setlocale (LC_ALL, "");
+  bindtextdomain ("bistromathic", LOCALEDIR);
+  textdomain ("bistromathic");
+#endif
+
   // Enable parse traces on option -p.
   if (argc == 2 && strcmp (argv[1], "-p") == 0)
     yydebug = 1;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.