我正在尝试为我的C / C ++ / C#/ Java / D类编程语言编写扫描程序,这是我出于个人原因设计的。为此,我正在使用Ragel生成扫描仪。我很难理解许多操作员何时触发行动,可能是因为我的学者专注于实践知识而非理论,而且大量的这种非确定性/确定性有限自动机业务正好在我脑海中。我发现文档要么缺乏,要么我对它的理解是如此。我假设后者。
无论如何,我正在从基础开始。我在第一次迭代中发现了几个关键字和特殊字符。现在我遇到了所有关键字都被扫描为标识符的问题。我正在使用扫描程序运算符来处理我的所有关键字,因为这解决了我的问题字符串returns
被扫描为return
和returns
关键字。
如何正确扫描标识符?我理解为了使这个确定性,我需要有效地指定lexeme只能是identifier
,如果它不匹配其他令牌的模式。原谅我缺乏知识。
Ragel脚本:
%%{
Identifier = (alpha | '_') . (alnum | '_')*;
action IdentifierAction
{
std::cout << "identifier(\"";
std::cout.write(ts, te - ts);
std::cout << "\")";
}
}%%
%%{
main :=
|*
Interface => InterfaceAction;
Class => ClassAction;
Property => PropertyAction;
Function => FunctionAction;
TypeQualifier => TypeQualifierAction;
OpenParenthesis => OpenParenthesisAction;
CloseParenthesis => CloseParenthesisAction;
OpenBracket => OpenBracketAction;
CloseBracket => CloseBracketAction;
OpenBrace => OpenBraceAction;
CloseBrace => CloseBraceAction;
Semicolon => SemicolonAction;
Returns => ReturnsAction;
Return => ReturnAction;
Identifier => IdentifierAction;
space+;
*|;
}%%
答案 0 :(得分:6)
不熟悉Ragel,但是,做过一些自定义解析器&amp;扫描仪。
您的问题似乎与检测关键字有关,而不是检测通用标识符。
你有规则要求Ragel检测代码是一个数字的部分,“return”关键字,分号,“returns”关键字,标识符等等。 Altought,可以为每个关键字制定规则,我不建议。
我从经验中学到的是,最好将所有关键字明确作为标识符(分配一般的“标识符”标记),并在C / C ++代码的某些部分中,检测哪些标识符是“关键字”。
换句话说。 Ragel将只检测标识符。 “myvar”,“return”和“return”都将被标记为“标识符”。稍后,在语义操作的代码( C / C ++而不是Ragel )中,您将检查每个标识符,并检测C / C ++中是否为关键字。这通常是通过提供关键字列表来完成的。
我认为会是这样的:
%%{
Identifier = (alpha | '_') . (alnum | '_')*;
action IdentifierAction
{
String Keywords[] =
(
"return",
"if",
"else"
);
String MyIdentifier = te - ts;
if (SearchKeywordCode(Keywords, MyIdentifier)) {
std::cout << "keyword(\"";
std::cout.write(ts, te - ts);
std::cout << "\")";
}
else {
std::cout << "identifier(\"";
std::cout.write(ts, te - ts);
std::cout << "\")";
}
}
}%%
所以,没有“返回”或“退货”规则,只有“标识符”。