正则表达式解析器 我最近一直在学习基础知识,作为实践,我决定在C++环境下实现一个DFA。所以基本上是正则表达式。当我从头开始构建树时,它工作得很好,但是我不确定如何处理正则表达式

正则表达式解析器 我最近一直在学习基础知识,作为实践,我决定在C++环境下实现一个DFA。所以基本上是正则表达式。当我从头开始构建树时,它工作得很好,但是我不确定如何处理正则表达式,c++,regex,parsing,dfa,C++,Regex,Parsing,Dfa,我的意思是,如果我有一个正则表达式,例如(test)*,我必须将其转换为DFA。问题是,为了做到这一点,我必须解析正则表达式。这似乎是一个恶性循环(更糟糕的是,我实际上需要一个括号识别解析器,正则表达式在这里不起作用) 那么如何应对呢?我完全理解我们现在有工具来做这件事(例如Flex和Bison),但这些工具是基于正则表达式的(至少标记化程序是这样的)。那么一开始发生了什么?如何从头开始编写正则表达式解析器?任何对书籍/文章的引用都值得欣赏。我曾经编写过自己版本的Flex,它生成了一组类而不是整

我的意思是,如果我有一个正则表达式,例如
(test)*
,我必须将其转换为DFA。问题是,为了做到这一点,我必须解析正则表达式。这似乎是一个恶性循环(更糟糕的是,我实际上需要一个括号识别解析器,正则表达式在这里不起作用)


那么如何应对呢?我完全理解我们现在有工具来做这件事(例如Flex和Bison),但这些工具是基于正则表达式的(至少标记化程序是这样的)。那么一开始发生了什么?如何从头开始编写正则表达式解析器?任何对书籍/文章的引用都值得欣赏。

我曾经编写过自己版本的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
这样编写的算法将为您提供一个标记器例程,它将元素分解为逻辑标记。然后必须将它们处理到表达式树中,这可以通过实现

您可以检查我的解析器生成器,尽管它生成了一个Delphi代码。不幸的是,自述文件是波兰语的,但里面有一些例子。例如:

Number=[0-9]+
Operator=[\+\-\*/]

顺便说一下,你可以为自己生成解析器,然后简单地把它从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=\|

在解析器生成器出现之前,人们是手工编程的。就像他们在高级语言编译器出现之前编写汇编代码一样。@Barmar我明白这一点。但是,我不确定如果没有正则表达式,如何编写解析器?也许我只是把事情弄得太复杂了,我只是想学习一些东西。你写了很多代码< <代码> >或代码>开关< /Cord>语句。如果你从来没有编写过一个语言解析器而不需要一个正则表达式引擎来处理你的DFA,那就认为你自己是幸运的。(我对你所学的任何算法语言和编译器设计课程的质量都感到非常失望)。直到你手工编写一个符合你已经手工制作的DFA的标记器,你才真正活了下来。这是它自己的“特殊”世界。@TonyD Cue my simple?:)我不是,我想我必须先反转波兰符号:D
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=\|