我正在运行一个教育网站,为孩子们教授节目(12-15岁)。
由于他们并不都在解决方案的代码源中说英语,因此我们使用法语变量和函数名称。 但是,我们计划将内容翻译成其他语言(德语,西班牙语,英语)。为此,我想尽快翻译源代码。 我们主要有C / C ++代码。
我打算使用的解决方案:
是否已经有一些开源代码/项目可以做到这一点? (对于第1,2和4点)
如果没有,那么第一个中最困难的一点是:使用C / C ++解析器构建一个语法树,然后用它们的位置提取变量似乎是要走的路。你有其他想法吗?
感谢您的任何建议。
修改: 正如评论中所指出的,我还需要处理注释,但只有少数几个:完整的解决方案已经在纯文本中解释,然后我们展示了具有自解释变量/函数的代码源名。源代码很少超过30/40行,如果您已经知道代码在做什么,那么好的名称必须使它在没有注释的情况下可以理解。
其他信息:对于有兴趣的人来说,该网站是国际奥林匹克信息学和C / C ++的培训平台(至少是编程竞赛所需的最低要求)并不难理解12岁。
答案 0 :(得分:2)
你真的不需要一个C / C ++解析器,只是一个简单的词法分析器,它逐个为你提供代码元素。然后,您会得到很多{
,[
,213
,)
等您只需忽略并写入结果文件的内容。你只翻译由字母组成的字母(关键字除外),然后将它们放在输出中。
现在我想起来,就像这样简单:
bool is_letter(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
bool is_keyword(string &s)
{
return s == "if" || s == "else" || s == "void" /* rest of them */;
}
void translateCode(istream &in, ostream &out)
{
while (!in.eof())
{
char c = in.get();
if (is_letter(c))
{
string name = "";
do
{
name += c;
c = in.get();
} while (is_letter(c) && !in.eof());
if (is_keyword(name))
out << name;
else
out << translate(name);
}
out << c; // even if is_letter(c) was true, there is a new c from the
// while inside that was read (which was not letter), but
// not written, so would be written here.
}
}
我在编辑器中编写了代码,因此可能存在轻微错误。告诉我,如果有,我会解决它。
修改:说明:
代码所做的只是逐个字符地读取输入,输出它读取的任何非字母字符(包括空格,制表符和新行)。如果它确实看到一个字母,它将开始将所有以下字母放在一个字符串中(直到它到达另一个非字母)。然后,如果字符串是关键字,它将输出关键字本身。如果不是,则将其翻译并输出。
输出格式与输入完全相同。
答案 1 :(得分:2)
您确定需要完整的语法树吗?我认为进行词法分析以找到标识符就足够了,这更容易。然后排除也包含在头文件中的关键字和标识符。
原则上,您可能希望将具有相同英文名称的不同变量翻译成法语/德语中的不同单词 - 但是对于教育用途,这种情况的风险可能很小,一开始可能忽略不计。您可以通过使用一些消除歧义的准匈牙利语前缀来编写原始资料来回避问题,然后使用相同的翻译机制将其删除,以便向讲英语的最终用户显示。
在选择翻译之前,请务必让译员查看他们正在使用完整上下文翻译的名称。
答案 2 :(得分:2)
我真的认为你可以使用 clang (libclang)解析你的资源并做你想做的事情(see here for more information),好消息是他们有python绑定,这将使如果您想要访问翻译服务或类似的东西,您的生活会更轻松。
答案 3 :(得分:0)
我不认为替换代码中的标识符是个好主意。
首先,你不会得到像样的翻译。这里非常重要的一点是,翻译(特别是自动或相当愚蠢的翻译)会丢失和扭曲信息。实际上,你可能会得到比原版更糟糕的东西。
其次,如果要再次编译代码,编译器可能无法在已翻译的标识符中编译包含非英文字母的代码。
第三,如果用其他东西替换标识符,则需要确保不要用相同的单词替换2个或更多不同的标识符。这要么使代码不可编辑,要么破坏其逻辑。
第四,您必须确保不翻译来自语言标准库的保留字和标识符。翻译这些将使代码不可编辑且不可读。区分程序员定义的标识符与语言提供的标识符及其标准库可能不是一项非常简单的任务。
我所做的不是用他们的翻译替换标识符,而是将翻译作为评论提供给他们,例如:
void eat/*comer*/(int* food/*comida*/)
{
if (*food/*comida*/ <= 0)
{
printf("nothing to eat!"/*no hay que comer!*/);
exit/*salir*/(-1);
}
(*food/*comida*/)--;
}
这样,由于翻译错误,您不会丢失任何信息,也不会破坏代码。