mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33: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. ##
|
## Symbol kinds. ##
|
||||||
@@ -252,8 +257,17 @@ m4_define([b4_declare_symbol_enum],
|
|||||||
final void toString(W)(W sink) const
|
final void toString(W)(W sink) const
|
||||||
if (isOutputRange!(W, char))
|
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] == '"')
|
if (yystr[0] == '"')
|
||||||
{
|
{
|
||||||
strip_quotes:
|
strip_quotes:
|
||||||
@@ -280,9 +294,7 @@ m4_define([b4_declare_symbol_enum],
|
|||||||
{
|
{
|
||||||
put(sink, "end of input");
|
put(sink, "end of input");
|
||||||
return;
|
return;
|
||||||
}
|
}]])[
|
||||||
|
|
||||||
put(sink, yystr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]])
|
]])
|
||||||
|
|||||||
@@ -40,6 +40,29 @@ version(D_Version2) {
|
|||||||
]b4_user_post_prologue[
|
]b4_user_post_prologue[
|
||||||
]b4_percent_code_get([[imports]])[
|
]b4_percent_code_get([[imports]])[
|
||||||
import std.format;
|
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>.
|
* 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;
|
immutable int argmax = 5;
|
||||||
SymbolKind[] yyarg = new SymbolKind[argmax];
|
SymbolKind[] yyarg = new SymbolKind[argmax];
|
||||||
int yycount = yysyntaxErrorArguments(yyctx, yyarg, argmax);
|
int yycount = yysyntaxErrorArguments(yyctx, yyarg, argmax);
|
||||||
string res = "syntax error, unexpected ";
|
string res, yyformat;
|
||||||
res ~= format!"%s"(yyarg[0]);
|
import std.string;
|
||||||
if (yycount < argmax + 1)
|
switch (yycount)
|
||||||
{
|
{
|
||||||
for (int yyi = 1; yyi < yycount; yyi++)
|
case 1:
|
||||||
{
|
yyformat = YY_("syntax error, unexpected %s");
|
||||||
res ~= yyi == 1 ? ", expecting " : " or ";
|
res = format(yyformat, yyarg[0]);
|
||||||
res ~= format!"%s"(SymbolKind(yyarg[yyi]));
|
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);
|
yyerror(]b4_locations_if([yyctx.getLocation(), ])[res);
|
||||||
}]],
|
}]],
|
||||||
[[simple]], [[
|
[[simple]], [[
|
||||||
yyerror(]b4_locations_if([yyctx.getLocation(), ])["syntax error");]])[
|
yyerror(]b4_locations_if([yyctx.getLocation(), ])[YY_("syntax error"));]])[
|
||||||
}
|
}
|
||||||
|
|
||||||
]b4_parse_error_bmatch(
|
]b4_parse_error_bmatch(
|
||||||
|
|||||||
@@ -13953,6 +13953,66 @@ or nonzero, full tracing.
|
|||||||
Identify the Bison version and skeleton used to generate this parser.
|
Identify the Bison version and skeleton used to generate this parser.
|
||||||
@end deftypecv
|
@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
|
@node D Parser Context Interface
|
||||||
@subsection D Parser Context Interface
|
@subsection D Parser Context Interface
|
||||||
The parser context provides information to build error reports when you
|
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>;
|
%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 */
|
/* Bison Declarations */
|
||||||
%token EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of file")], ["end of input"])[
|
%token EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of file")], ["end of input"])[
|
||||||
%token <ival> NUM "number"
|
%token <ival> NUM "number"
|
||||||
@@ -665,7 +682,7 @@ m4_define([_AT_DATA_CALC_Y(d)],
|
|||||||
STAR "*"
|
STAR "*"
|
||||||
SLASH "/"
|
SLASH "/"
|
||||||
POW "^"
|
POW "^"
|
||||||
EOL "\n"
|
EOL "'\\n'"
|
||||||
LPAR "("
|
LPAR "("
|
||||||
RPAR ")"
|
RPAR ")"
|
||||||
NOT "!"
|
NOT "!"
|
||||||
|
|||||||
Reference in New Issue
Block a user