一个重要的细节是,语法不“接受”字符串;它们生成字符串。语法是语言的描述,提供一种生成语言中包含的所有可能字符串的方法。为了确定特定字符串是否包含在语言中,您将使用识别器,一种处理给定字符串并回答“是”或“否”的自动机。
上下文无关文法(CFG)是一种语法,其中(如您所指出的)每个产生式的形式为A→w,其中A是非终端符号,w是终端符号和非终端符号的字符串。非正式地说,CFG是一种语法,其中任何非终端符号都可以在任何时候扩展到其任何产生式之一。语法的语言是可以从起始符号派生的终端符号字符串集合。
上下文敏感文法(CSG)是一种语法,其中每个产生式的形式为wAx→wyx,其中w和x是终端符号和非终端符号的字符串,y也是终端符号的字符串。换句话说,这些产生式提供了规则,即“如果您在给定上下文中看到A,则可以将A替换为字符串y。”不幸的是,这些语法被称为“上下文敏感语法”,因为它意味着“上下文无关”和“上下文敏感”不是相反的,这意味着有某些类别的语法,它们可能考虑了大量的上下文信息,但在形式上并不被认为是上下文敏感的。
要确定一个字符串是否包含在CFG或CSG中,有很多方法。首先,您可以为给定的语法构建识别器。对于CFG,下推自动机(PDA)是一种接受上下文无关语言的自动机类型,并且有一个简单的构造方法可以将任何CFG转换为PDA。对于上下文敏感语法,您需要使用的自动机称为线性有界自动机(LBA)。
然而,如果天真地处理这些方法,它们并不是非常有效。为了确定一个字符串是否包含在CFG的语言中,有更有效的算法。例如,许多语法可以为它们构建
LL(k)或
LR(k)解析器,这使您能够(在线性时间内)决定一个字符串是否包含在语法中。所有语法都可以使用
Earley解析器进行解析,该解析器可以在O(n
3)中确定长度为n的字符串是否包含在语法中(有趣的是,它可以在O(n
2)中解析任何不含歧义的CFG,并且具有前瞻性,可以在O(n)时间内解析任何LR(k)语法!)。如果您只对问题“字符串x是否包含在由语法G生成的语言中”感兴趣,则其中一种方法将非常出色。如果您想知道如何生成字符串x(通过查找
解析树),则可以将这些方法调整为提供此信息。然而,解析CSG通常是PSPACE完全的,因此没有已知的解析算法可以在最坏情况下多项式时间内运行。虽然有一些实际上往往运行得很快的算法。《解析技术:实用指南》(见下文)的作者已经组织了
一个包含各种解析算法的奇妙页面,其中包括解析上下文敏感语言的算法。
如果你对解析有兴趣,可以考虑阅读 Grune 和 Jacobs 的优秀书籍 "
Parsing Techniques: A Practical Guide, Second Edition"。该书讨论了各种解析算法,用于确定字符串是否包含在语法中,并确定它是如何由解析算法生成的。