c++ - 如何让 Ragel 执行不同的解析操作

标签 c++ fsm ragel

我是 Ragel 的新手,一直在尝试解析 Regex 表达式的特定模式。如果找到匹配项,我希望执行操作 done ,如果没有匹配项,即使缺少任何单个字符,我也希望执行 parse_error

这是我写的代码:

#include <iostream>
#include <string.h>
#include <stdio.h>

%%{
action done {
printf("done\n");
}


action parse_error {
printf("error : %c\n",fc);
}


machine ldf;    
main := (':'.'LoadSdf'.[0-9]+.[a-zA-Z0-9_\-\.])@done |    //execute done
         (^(':'.'LoadSdf'.[0-9]+.[a-zA-Z0-9_\-\.])) $err(parse_error); //execute parse error for no match

}%%

%%write data;
int main(int argc, char** argv)
{
int cs;
 if(argc > 1) {
char *p = argv[1];
char *pe = p+strlen(p) + 1;
%%write init;
%%write exec;
}
 return 0;
}

我看到的行为是当正则表达式完全匹配时,操作 doneparse_error 都会执行。

任何人都可以提供一些关于如何处理此案例的提示吗?

最佳答案

这段代码有几个问题。首先,一个技术错误 --- 你与 pe 定义不一致(它包含零字符,你的机器不应该关心零(当然你可以让它处理它们,但它无缘无故地使事情复杂化))。定义 eof 也很有用,因为当您在输入中有类似“:Load”的内容(缺少“Sdf”和后续 block )时,它应该是一个错误。这是固定的

-char *pe = p+strlen(p) + 1;
+char *pe = p+strlen(p);
+char *eof = pe;

另一个问题是没有必要结合一些机器和它的负面来控制错误。这些是不同的 Action 。看看你机器的图片:

Original state machine

你可以看到在中间没有适当的错误处理,最后你可以多次调用 done() 因为它被指定在转换到最终之一时发生状态。可能它只应该在正确的机器完成时运行(即,在最终状态下达到 EOF)。

因此,如果您要将机器定义更改为

main := (':'.'LoadSdf'.[0-9]+.[a-zA-Z0-9_\-\.]) %/done $!(parse_error);

你可能会得到你想要的:

$ ./a.out "asdf"
error : a
$ ./a.out "qwerty"
error : q
$ ./a.out ":Load"
error : 
$ ./a.out ":LoadSdf"
error : 
$ ./a.out ":LoadSdf1212"
done
$ ./a.out ":LoadSdf1q"
done
$ ./a.out ":LoadSdf1qwe"
error : w

图形形式看起来像这样:

Fixed state machine

关于c++ - 如何让 Ragel 执行不同的解析操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43345019/

相关文章:

parsing - ANTLR 是序列化/反序列化二进制数据格式的合适工具吗?

c++ - 使递归在 C++ 中更高效

c++ - G++ 6.1.0 中可能的回归

java - 用 python 生成 java 的最佳方法?

uml - 有条件转移的有限状态机可以表示为马尔可夫链吗?

lexical-analysis - 如何使用 Ragel 正确扫描标识符

c++ - 在 c++ 中为我的类设置/获取方法时遇到问题

c++ - sizeof 运算符在运行时发生变化?

algorithm - 如何创建可以处理同时发生的事件的有限状态机

xml - 如何编写一个简单的 Ragel 分词器(无回溯)?