我最近一直在学习基础知识,作为一种实践,我决定在C ++环境中实现DFA。所以基本上它是正则表达式。当我从头开始构建树时,它运行良好,但是我不知道如何处理正则表达式。
我的意思是,如果我有正则表达式,例如(test)*
我必须将其转换为DFA。问题是,为了做到这一点,我必须解析正则表达式。这似乎是一个恶性循环(更糟糕的是因为我实际上需要一个支架感知解析器,正则表达式在这里不起作用)。
那么如何应对呢?我完全理解我们现在有工具(例如Flex& Bison),但这些工具基于正则表达式(好吧,至少是标记器)。那么在开始时发生了什么?如何从头开始编写正则表达式解析器?对书籍/文章的任何提及都表示赞赏。
答案 0 :(得分:3)
我曾经编写过自己的Flex版本,它生成了一组类而不是整个程序。首先,我必须手工解析正则表达式,但是当我最终编写它时,我将正则表达式解析机制替换为程序本身生成的机制。
手动解析正则表达式实际上非常简单。首先,您必须指定要实现的结果。例如,在我的情况下:
[abc]+test
被解释为:
[abc]@[abc]*@[t]@[e]@[s]@[t]
实际上是等价的(@是人工添加的连接运算符)。
然后你必须创建一套规则,例如
'[' spotted:
- (optionally) expect '^' character;
- repeat:
- expect a non-special character;
- If it is not last character and is succeeded by '-', expect another character
- until `]` is spotted
- Return a character set
'(' spotted:
- Return a block-begin
')' spotted:
- Return a block-end
'*' spotted:
- Return a star-operator
'+' spotted:
- Return a plus-operator
'.' spotted:
- Return a whole character set
Any other char spotted:
- Return a character set consisting of this single character
这样编写的算法将为您提供一个tokenizer - 例程,它将元素分解为逻辑标记。然后你必须将它们处理成表达式树,这可以通过实现Reverse Polish Notation algorithm来解决。
您可以检查我的解析器生成器here,尽管它会生成Delphi代码。不幸的是,自述文件是波兰语,但内部有一些例子。试试例如:
Number=[0-9]+
Operator=[\+\-\*/]
和
SpkParserGenerator -i myfile.regex -mc -sg
顺便说一句,你可以为自己生成一个解析器,然后简单地将它从Delphi转换为C ++,即使你不熟悉Delphi,它实际上也很简单。
这是我用于为解析器生成器生成解析器的一组规则:
SetRange=\{([0-9]*,[0-9]+)|([0-9]+,[0-9]*)|([0-9]+)\}
Star=\*
Plus=\+
QMark=\?
CharRange=\[\^?((\\.)|(\#[0-9]{3})|([^\\\#\]]))+\]
AnyChar=\.
EscapedChar=\\.
AsciiChar=\#[0-9]{3}
Char=[^\[\]\{\}\.\(\)\#\*\+\?\|\\]
OpenParenthesis=\(
CloseParenthesis=\)
Alternative=\|