Ragel:如何匹配其他不匹配的东西?

时间:2015-02-25 16:42:11

标签: state-machine ragel

我使用Ragel实现了一个非常简单的解析器。 “主要”结构是扫描仪。

我实现了类似的东西:

action doSomething
{
    doSomething(fpc);
}

foo = 'foo';
bar = 'bar';

main := |*

    foo => { matchFoo(); };
    bar => { matchBar(); };
    space;

*|;

如何匹配其他规则不匹配的其他规则(即基本上是错误条件,某种格式错误的输入)?我想实现它,以便能够在格式错误的输入的哪一行上出错。我尝试在扫描仪的末尾使用“任何”条件但当然不起作用,因为这将始终是“最长匹配”,因此扫描仪每次都会匹配它。我肯定不想从包含所有其他令牌的列表中取一些否定(从'any'中排除它们),因为这听起来很错误(难以维护并最终成为包含许多令牌的大量代码) 。如何匹配Ragel扫描仪中与其他东西不匹配的其他内容?

编辑:做了一些测试,如果我只是在扫描仪的末尾匹配“任何”,我可以让它工作。然后当角色不匹配时它将转到该表达式。但是,如果我尝试匹配“任何+”,那么它将不起作用,因为它将每次都去那里(对于所有数据,它将始终是扫描仪中最长的匹配)。只匹配“any”的问题是我没有得到令牌开始和令牌结束指针到WHOLE连续块的不匹配数据。如何匹配“与其他任何内容不匹配的最长连续字符块”?

1 个答案:

答案 0 :(得分:1)

我会跟踪我的有效输入何时结束,并将其与新的有效输入开始时进行比较。因此介于两者之间的任何东西都是无效的像这样:

foo = 'foo';
bar = 'bar';

action doFoo {
    if (ts > gs) handleError();
    gs = te;
    matchFoo();
}

action doBar {
    if (ts > gs) handleError();
    gs = te; 
    matchBar();
}

action doSpace {
    if (ts > gs) handleError();
    gs = te;
}

main := |*

    foo =>   doFoo;
    bar =>   doBar;
    space => doSpace;
    any;

*|;

通过将gspe进行比较,您还必须在Ragel完成后检查输入结尾处的垃圾。

请注意,我还没有测试过这台机器,但是我已经通过Ragel运行了它,并查看了机器的GraphViz图表。