【问题标题】:Parser for regular expressions正则表达式解析器
【发布时间】:2014-03-18 08:08:43
【问题描述】:

我最近一直在学习基础知识,作为一种实践,我决定在 C++ 的上下文中实现 DFA。所以基本上它是正则表达式。当我从头开始构建树时效果很好,但是我不确定如何处理正则表达式。

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

那么怎么处理呢?我完全理解我们现在有工具可以做到这一点(例如 Flex 和 Bison),但是这些工具是基于正则表达式的(嗯,至少标记器是)。那么一开始发生了什么?如何从头开始编写正则表达式解析器?任何对书籍/文章的引用表示赞赏。

【问题讨论】:

  • 在解析器生成器出现之前,人们手动对其进行编程。就像他们在高级语言编译器出现之前编写汇编代码一样。
  • @Barmar 我明白这一点。但是我不确定如何编写一个没有正则表达式的解析器?也许我只是把事情复杂化了,我只是想学习一些东西。
  • 你写了很多 ifswitch 语句。
  • 如果您从来没有编写过语言解析器而没有使用正则表达式引擎来处理您的 DFA,那么认为自己很幸运(而且我对您的任何算法语言和编译器设计课程的质量感到非常失望拿)。在您编写一个标记器以符合您已经手工制作的 DFA 手工之前,您还没有真正生活。这是它自己的“特殊”世界。
  • @TonyD 提示我的简单 Regex Parser written with Boost Spirit? :)

标签: c++ regex parsing dfa


【解决方案1】:

我曾经编写过自己的 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

这样编写的算法将为您提供一个分词器 - 例程,它将元素分解为逻辑令牌。然后你必须将它们处理成一个表达式树,这可以通过实现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=\|

【讨论】:

  • 我不是,我想我得先反转波兰表示法:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-17
  • 1970-01-01
相关资源
最近更新 更多