Regex 正则表达式是否用于构建解析器?

Regex 正则表达式是否用于构建解析器?,regex,parsing,Regex,Parsing,这只是一个出于好奇的问题,因为我最近需要越来越多地分析和使用正则表达式。。似乎,对于我在搜索中遇到的关于某种语法分析的问题,当被问及与regex有关的问题时,总会有人说,“regex不适合这样做,请改用某某语法分析程序”。。。随着我对正则表达式的进一步理解,我认为大多数东西都是可能的,只是它相当复杂和耗时,因为您必须考虑许多不同的可能性,当然,它必须与条件语句和循环相结合,以构建任何类型的解析器。。所以我想知道是用正则表达式来构建大多数解析器,还是使用了其他方法。。我只是想知道,因为我可能需要构

这只是一个出于好奇的问题,因为我最近需要越来越多地分析和使用正则表达式。。似乎,对于我在搜索中遇到的关于某种语法分析的问题,当被问及与regex有关的问题时,总会有人说,“regex不适合这样做,请改用某某语法分析程序”。。。随着我对正则表达式的进一步理解,我认为大多数东西都是可能的,只是它相当复杂和耗时,因为您必须考虑许多不同的可能性,当然,它必须与条件语句和循环相结合,以构建任何类型的解析器。。所以我想知道是用正则表达式来构建大多数解析器,还是使用了其他方法。。我只是想知道,因为我可能需要构建一些相当复杂的自定义解析器,而这些解析器并不一定要使用现有的解析器


感谢您提供的任何信息,因为我似乎找不到对此的直接答案。

不,解析器是从中构建的

但是大多数编译器(解释器)将使用单独的扫描仪(lexer)来识别输入标记。扫描器可以用正则表达式指定,但它们不是使用常用的正则表达式库类构建的

单独的扫描仪是一种实用的方法。可以定义完整的语法,一直到字符级别,但这是不切实际的。正则表达式更容易处理语法的端点子集


有关参考,请参阅。他们都有现代接班人

regex是创建确定性有限自动机的一种特殊符号。DFA是一种解析设备,因此regexp进行解析。当您使用regexp来匹配某个内容时,您正在解析字符串以使其与模式对齐。当您使用regexp用括号将某些内容切分为位时,您就是在解析

DFA被正式定义为特定类别语言的解析器,称为“常规语言”(感谢Gumbo提醒我)。许多重要任务不涉及常规语言

因此,DFA不是解决许多解析问题的好方法。这里最著名的例子是XML和HTML。原因有很多,但我会补充一个。这些基本上是树结构。要解析它们,程序必须在树下时保持状态。regexp不会这样做

语法定义的解析器(如LR(k)和LL(k))实现了这一点,自顶向下的手工编码解析器实现了这一点


有关于各种可供选择的解析技术的书籍和书籍,这些技术通常用于分析诸如C++或XML之类的东西。

(多数)解析器是为递归语言创建的。regexp不能处理递归性,因此它们不用于解析器构造(没有额外的技巧,比如说Perl标记)。然而,regexp用于开发lexer,因为这样做会使工作更轻松。

好吧,构建解析器相当复杂,您可以使用regex,但这不是您唯一使用的东西。我建议读一下这本书


现在,在我看来,您应该使用解析器生成器,因为您可以从头开始,但它既不简单也不快速。一般来说,你必须考虑正则表达式和有限状态自动机进行词法分析;上下文无关语法、LL解析器、自底向上解析器和用于语法分析的LR解析器等等。

通常,在词法分析器中使用某种模式匹配(不一定是正则表达式),将字符流转换为令牌流,并让解析器查看这些令牌,而不是原始字符输入


如果您希望生成自己的解析器,那么最好使用类似的方法来帮助您实现这一点。

正则表达式可以用于解析特定类别的语言(有限状态语言),但与其他形式相比,它们的功能有限,正如您所提到的,它们很快就会变得不适,难以维护

例如,不可能有一个正则表达式来确保每个开括号都有一个匹配的闭括号,这是大多数语言在表达式语法中都有的

正则表达式通常用于进行标记化,然后将标记组合起来以创建所需的语法。

通常,在构建解析器时,您将使用两种(至少)类型的工具

第一部分是词法分析——将字符分成标记,过滤掉注释和空白。这一部分通常是用正则表达式完成的。更典型的是,它使用扫描生成器来完成,扫描生成器将一对正则表达式和代码的集合转换为一个程序,该程序在识别正则表达式时执行相应的代码。事实证明,这比每次测试每个正则表达式更有效,而且由于各种其他原因,它的效果也更好。FLEX是C中用于此目的的常用工具

解析器的第二部分是语法。最典型的工具是另一个程序生成器,它接受上下文无关语法(CFG),并用解释“词类”组件的规则进行注释。CFG能够表达平衡括号之类的东西,而正则表达式不能(除非它使用CF特性进行了扩展,使其在数学意义上不是严格的“正则”)。但是带有规则的CFG非常好,因为您可以将语义附加到语言的短语结构中。野牛是C中这一部分的常用工具

但我实际上告诉了你一个小谎言。你看,每一种真正的编程语言都有不能在上下文无关的框架中表达的部分。例如,您需要将变量的定义与它的使用联系起来,以便知道要生成什么指令,以及对它的操作是否合法。这通常不在parsi的范围内
 LHS =  RHS1 RHS2 ... RHSn ;
 EBNF = RULE+ ;
 RULE = IDENTIFIER '=' ALTERNATIVES ';' ;
 ALTERNATIVES = RHS ( '|' RHS )* ;
 RHS = ITEM* ;
 ITEM = IDENTIFIER | QUOTEDTOKEN | '(' ALTERNATIVES ')' | ITEM ( '*' | '+' ) ;