mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
d: add internationalisation support
The D parser implements this feature similarly to the C parser, by using Gettext. Functions gettext() and dgettext() are imported using extern(C). The internationalisation uses yysymbol_name to report the name of the SymbolKinds. * data/skeletons/d.m4 (SymbolKind.toString.yytranslatable, SymbolKind.toString.yysymbol_name: New), data/skeletons/lalr1.d: Here. * doc/bison.texi: Document it. * tests/calc.at: Test it.
This commit is contained in:
committed by
Akim Demaille
parent
e51e89856a
commit
594cae57ca
@@ -192,7 +192,12 @@ b4_symbol_foreach([b4_token_enum])dnl
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
# b4_symbol_translate(STRING)
|
||||
# ---------------------------
|
||||
# Used by "bison" in the array of symbol names to mark those that
|
||||
# require translation.
|
||||
m4_define([b4_symbol_translate],
|
||||
[[_($1)]])
|
||||
|
||||
## -------------- ##
|
||||
## Symbol kinds. ##
|
||||
@@ -252,8 +257,17 @@ m4_define([b4_declare_symbol_enum],
|
||||
final void toString(W)(W sink) const
|
||||
if (isOutputRange!(W, char))
|
||||
{
|
||||
string yystr = yytname_[yycode_];
|
||||
immutable string[] yy_sname = @{
|
||||
]b4_symbol_names[
|
||||
@};]b4_has_translations_if([[
|
||||
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
|
||||
internationalizable. */
|
||||
immutable ]b4_int_type_for([b4_translatable])[[] yytranslatable = @{
|
||||
]b4_translatable[
|
||||
@};
|
||||
|
||||
put(sink, yy_sname[yycode_]);]], [[
|
||||
string yystr = yytname_[yycode_];
|
||||
if (yystr[0] == '"')
|
||||
{
|
||||
strip_quotes:
|
||||
@@ -280,9 +294,7 @@ m4_define([b4_declare_symbol_enum],
|
||||
{
|
||||
put(sink, "end of input");
|
||||
return;
|
||||
}
|
||||
|
||||
put(sink, yystr);
|
||||
}]])[
|
||||
}
|
||||
}
|
||||
]])
|
||||
|
||||
@@ -40,6 +40,29 @@ version(D_Version2) {
|
||||
]b4_user_post_prologue[
|
||||
]b4_percent_code_get([[imports]])[
|
||||
import std.format;
|
||||
import std.conv;
|
||||
|
||||
/**
|
||||
* Handle error message internationalisation.
|
||||
*/
|
||||
static if (!is(typeof(YY_))) {
|
||||
version(YYENABLE_NLS)
|
||||
{
|
||||
version(ENABLE_NLS)
|
||||
{
|
||||
extern(C) char* dgettext(const char*, const char*);
|
||||
string YY_(const char* s)
|
||||
{
|
||||
return to!string(dgettext("bison-runtime", s));
|
||||
}
|
||||
}
|
||||
}
|
||||
static if (!is(typeof(YY_)))
|
||||
{
|
||||
pragma(inline, true)
|
||||
string YY_(string msg) { return msg; }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
|
||||
@@ -680,20 +703,38 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
immutable int argmax = 5;
|
||||
SymbolKind[] yyarg = new SymbolKind[argmax];
|
||||
int yycount = yysyntaxErrorArguments(yyctx, yyarg, argmax);
|
||||
string res = "syntax error, unexpected ";
|
||||
res ~= format!"%s"(yyarg[0]);
|
||||
if (yycount < argmax + 1)
|
||||
string res, yyformat;
|
||||
import std.string;
|
||||
switch (yycount)
|
||||
{
|
||||
for (int yyi = 1; yyi < yycount; yyi++)
|
||||
{
|
||||
res ~= yyi == 1 ? ", expecting " : " or ";
|
||||
res ~= format!"%s"(SymbolKind(yyarg[yyi]));
|
||||
}
|
||||
case 1:
|
||||
yyformat = YY_("syntax error, unexpected %s");
|
||||
res = format(yyformat, yyarg[0]);
|
||||
break;
|
||||
case 2:
|
||||
yyformat = YY_("syntax error, unexpected %s, expecting %s");
|
||||
res = format(yyformat, yyarg[0], yyarg[1]);
|
||||
break;
|
||||
case 3:
|
||||
yyformat = YY_("syntax error, unexpected %s, expecting %s or %s");
|
||||
res = format(yyformat, yyarg[0], yyarg[1], yyarg[2]);
|
||||
break;
|
||||
case 4:
|
||||
yyformat = YY_("syntax error, unexpected %s, expecting %s or %s or %s");
|
||||
res = format(yyformat, yyarg[0], yyarg[1], yyarg[2], yyarg[3]);
|
||||
break;
|
||||
case 5:
|
||||
yyformat = YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
|
||||
res = format(yyformat, yyarg[0], yyarg[1], yyarg[2], yyarg[3], yyarg[4]);
|
||||
break;
|
||||
default:
|
||||
res = YY_("syntax error");
|
||||
break;
|
||||
}
|
||||
yyerror(]b4_locations_if([yyctx.getLocation(), ])[res);
|
||||
}]],
|
||||
[[simple]], [[
|
||||
yyerror(]b4_locations_if([yyctx.getLocation(), ])["syntax error");]])[
|
||||
yyerror(]b4_locations_if([yyctx.getLocation(), ])[YY_("syntax error"));]])[
|
||||
}
|
||||
|
||||
]b4_parse_error_bmatch(
|
||||
|
||||
@@ -13953,6 +13953,66 @@ or nonzero, full tracing.
|
||||
Identify the Bison version and skeleton used to generate this parser.
|
||||
@end deftypecv
|
||||
|
||||
The internationalization in D is very simmilar to the one in C. The D
|
||||
parser uses @code{dgettext} for translating Bison messages.
|
||||
|
||||
To enable internationalisation, compile using
|
||||
@code{-version ENABLE_NLS -version YYENABLE_NLS} and import
|
||||
@code{bindtextdomain} and @code{textdomain} from C:
|
||||
|
||||
@example
|
||||
extern(C) char* bindtextdomain(const char* domainname, const char* dirname);
|
||||
extern(C) char* textdomain(const char* domainname);
|
||||
@end example
|
||||
|
||||
The main function should load the translation catalogues, similarly to the
|
||||
@file{c/bistromathic} example:
|
||||
|
||||
@example
|
||||
int main()
|
||||
@{
|
||||
import core.stdc.locale;
|
||||
|
||||
// Set up internationalization.
|
||||
setlocale(LC_ALL, "");
|
||||
// Use Bison's standard translation catalogue for error messages
|
||||
// (the generated messages).
|
||||
bindtextdomain("bison-runtime", BISON_LOCALEDIR);
|
||||
// For the translation catalogue of your own project, use the
|
||||
// name of your project.
|
||||
bindtextdomain("bison", LOCALEDIR);
|
||||
textdomain("bison");
|
||||
|
||||
// usual main content
|
||||
...
|
||||
@}
|
||||
@end example
|
||||
|
||||
For user messages translations, the user must implement the
|
||||
@code{string} _(@code{const char*} @var{msg}) function and it is recommended
|
||||
to use @code{gettext}:
|
||||
|
||||
@example
|
||||
%code imports @{
|
||||
static if (!is(typeof(_)))
|
||||
@{
|
||||
version(ENABLE_NLS)
|
||||
@{
|
||||
extern(C) char* gettext(const char*);
|
||||
string _(const char* s)
|
||||
@{
|
||||
return to!string(gettext(s));
|
||||
@}
|
||||
@}
|
||||
@}
|
||||
static if (!is(typeof(_)))
|
||||
@{
|
||||
pragma(inline, true)
|
||||
string _(string msg) @{ return msg; @}
|
||||
@}
|
||||
@}
|
||||
@end example
|
||||
|
||||
@node D Parser Context Interface
|
||||
@subsection D Parser Context Interface
|
||||
The parser context provides information to build error reports when you
|
||||
|
||||
@@ -654,6 +654,23 @@ m4_define([_AT_DATA_CALC_Y(d)],
|
||||
};
|
||||
%printer { fprintf (yyo, "%d", $$); } <ival>;
|
||||
|
||||
%code {
|
||||
]AT_TOKEN_TRANSLATE_IF([[
|
||||
static string _(string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "end of input":
|
||||
return "end of file";
|
||||
case "number":
|
||||
return "nombre";
|
||||
default:
|
||||
return s;
|
||||
}
|
||||
}
|
||||
]])[
|
||||
}
|
||||
|
||||
/* Bison Declarations */
|
||||
%token EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of file")], ["end of input"])[
|
||||
%token <ival> NUM "number"
|
||||
@@ -665,7 +682,7 @@ m4_define([_AT_DATA_CALC_Y(d)],
|
||||
STAR "*"
|
||||
SLASH "/"
|
||||
POW "^"
|
||||
EOL "\n"
|
||||
EOL "'\\n'"
|
||||
LPAR "("
|
||||
RPAR ")"
|
||||
NOT "!"
|
||||
|
||||
Reference in New Issue
Block a user