4

我正在尝试为我出于个人原因设计的类似 C/C++/C#/Java/D 的编程语言编写扫描仪。对于这个任务,我使用 Ragel 来生成我的扫描仪。我无法准确理解许多操作员何时触发操作,这可能是因为我的学者专注于实践知识而不是理论,而且这种非确定性/确定性有限自动机业务的大部分内容都在我脑海中浮现。我发现文档要么缺乏,要么我对它的理解如此。我假设后者。

无论如何,我正在从基础开始。我在第一次迭代中确定了几个关键字和特殊字符。现在我遇到了所有关键字都被扫描为标识符的问题。我对所有关键字都使用了扫描仪运算符,因为这解决了我的字符串returns被扫描为returnandreturns关键字的问题。

如何正确扫描标识符?我知道要使这种确定性具有确定性,我需要有效地指定一个词位只能是一个,identifier如果它不匹配其他令牌的模式。原谅我缺乏知识。

拉格尔脚本:

%%{
    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+;
    *|;
}%%
4

1 回答 1

6

不熟悉 Ragel,但做过一些自定义解析器和扫描器。

您的问题似乎与检测关键字有关,而不是检测通用标识符。

您有规则告诉 Ragel 检测代码何时是数字、“return”关键字、分号、“returns”关键字、标识符等的部分。Altought,可以为每个关键字制定规则,我不会推荐。

我从经验中学到的是,最好将所有关键字明确地读取为标识符(分配一个通用的“标识符”标记),并在 C/C++ 代码的某些部分检测哪些标识符是“关键字”。

换句话说。Ragel 将仅检测标识符。“myvar”、“return”和“returns”都将被标记为“标识符”。稍后,在您的语义操作代码中(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 << "\")";
    }
}
}%%

因此,没有“返回”或“返回”规则,只有“标识符”。

于 2011-03-14T17:59:02.000 回答