我正在尝试创建一个允许有限的用户定义替换规则的文本解析器。
即使我正在读取DOS ASCII文件中的代码,其中订购很重要并且必须保持行编号。使用此输入,我想应用用户定义的替换规则(为该字符串交换此字符串,如果我们看到此字符串后跟该字符串执行此转换等)。
输出也是格式化的DOS ASCII文件。
大多数规则都是直接替换针对tat类型的替换,但是,在某些情况下我想要定义一个规则,例如如果A在将来的任何时间点后面跟着B,请应用此规则。
要做到这一点,我正在使用结构树本身:
struct node {
list<string> common; // the text which is not affected by conditions
string condition; // matching this string selects the left, otherwise the right
node *lptr, *rptr; // pointers to the child nodes, if needed
};
每当我遇到这样的规则时,我都可以通过省略和应用规则来维护输出,从而延迟决定使用哪个直到明确地解决它。
这有点浪费内存,但似乎是避免必须两次传递输入数据的最佳方法(输入数据的大小未知,但可能不到1兆)。
当然可能存在这样一种情况:这种类型的不同规则在一个或两个子节点内触发,这就是树结构的原因。
没有限制孩子必须在父母面前做出决定,可能是父母只能在孩子的一个分支上进行决定。遇到EOF会让任何未定的孩子处于错误的方向。
所以很明显我在倒带和折叠节点时一定要小心。
这个一般性问题是否有更简单的解决方案?有没有办法以比我的树更有效的方式使用标准库容器?
答案 0 :(得分:0)
您可能需要查看NFA和DFA,即非确定性有限状态自动和确定性有限状态自动。这两种方法是编写器解析器最常用且通常非常有效的方法。
实际上不需要将数据存储在节点中,否则它将被传递并浪费内存。更好的方法是,分配一个变量(比如int state = 0)来跟踪当前的解析状态。根据当前状态和输入,您的算法将改变状态。状态总是向前发展,但如果某个条件不匹配(称为“回溯”),您可以告诉您的算法返回到之前的状态。
E.g。如果“ab”和“ac”是两个有效输入,解析“ac”时算法可能是这样的:
char is 'a' ==> go to state.checkB
char is not 'b' ==> go back to state.checkA
checkB was already done ==> go to state.checkC
char is 'c' ==> DoSomething();
需要大量的文章和图表来完整地解释所有内容,希望这能让您知道在哪里进一步了解。
答案 1 :(得分:0)
假设通过'文本解析器',你的意思是你试图压缩相同含义的单词和短语,以简化对命令的反应。
在这种情况下,根据旧的文本冒险程序,使用规则查找表的简单左右解析器可以在这里工作。
除非我误解了您的问题域,否则您的解决方案似乎过度设计了。
答案 2 :(得分:0)
听起来你应该试试正则表达式。以下是有关选择图书馆的讨论链接:C++ RegEx Library Choice。 Boost很受欢迎。
另外,您是否考虑过使用其他语言来解决问题? Python有一个很好的有用库库,包括一个用于正则表达式(import re)。如果它在您的驾驶室中,您可能会发现它比C ++解决方案更容易。
最后,考虑使用“已定义”的文本格式而不是输入文件的自定义格式。 XML是一个不错的选择。在XML树中嵌套规则可能更容易。 C ++你可以使用Expat XML Parser(Python将是xml.etree.ElementTree)。