Answers:
解析器的输出不必是树。确实,当您考虑诸如从变量的使用到覆盖在抽象语法树上的DEFinition的引用之类的事情时,您会立即得到一个图。
关键是解析通常设计为一次通过–这很重要,因为历史原因,例如空间和处理器速度不足,而且原因很简单。然后,后续阶段将使用附加信息来装饰解析树。
有一些图语法,尽管我不知道它们是否用于解析编程语言。
OP的问题有些落后。当然,解析算法可以输出所需的任何内容。问题更多的是要了解解析的目的以及解析器是否输出满足此目标的结果。然后,您可能会想知道什么是合适的表示形式,例如树或图。
好吧,我想解析器是一种算法,它将根据语言语法的给定形式定义,为您提供作为输入的句子的句法结构。
请注意,人们可能会在语言的语法构成上存在分歧。有些可能将其限制为纯粹的形式语言主干,而另一些可能引入更多的语义考虑,例如类型,体裁,数字或其他更复杂的考虑(我不区分NLP或编程语言)。大多数语言具有要求表示图的功能,但是要由“执行者”(由于缺少更好的词)来决定他是否要在语法中包括该图。
因此,根据所定义的语法,您可能必须输出另一种形式的结构。
在纯上下文无关的简单解析情况下,解析树可能会起作用,除了以下解决的歧义问题,或者您可能需要稍加修改以获得AST的事实(请参见下文)。
但是,在更复杂的情况下,您可能需要不同的结构,这些结构通常由树中的链接表示,从而导致图形结构。这在很大程度上取决于您对语言语法的定义。
另外,您应该输出的树也不明显。如果以树邻接语法(TAG)为例,它们的工作方式是语法树与派生树不同,尽管前者可以从后者派生。您要输出的内容可能是一个相关的问题。
关于歧义性还有另一个问题。给定的句子虽然属于您的语言,但可以通过许多不同的方式进行操作,但是可以通过许多不同的方式为其分配语法结构。
然后,您可以选择仅输出这些结构之一,可以随机选择或根据定义明确的标准(例如,似然性)进行选择。您也可以选择输出其中的几个或全部。如果要输出多个文件,通常打包起来很方便,然后打包成一个独特的结构,可以共享它们的共同点。这节省了空间和计算时间,而复杂性可能是一个实际问题。
选择输出所有它们时,您别无选择,只能共享,因为可能存在无限数量的可能的解析。只有通过某种方式在图形中具有一个循环,才能无限地表示无限。因此,您通常必须产生一个图结构。但是该图结构的属性与您选择的形式语法有关。
现在的问题也是关于抽象语法树。我跳过了“抽象”部分,因为它会带来混乱,恕我直言。确实,这个问题在其各种重述中已经令人困惑。
关于AST,从历史的角度来看,它们起源于1960-1970年间的Lisp语言和程序操纵系统。想法是将程序视为大型表达式,作为数学公式,既用于操纵目的,又用于分析属性或以正式方式定义语义,数学家知道如何对公式进行运算。按照公式,它们自然是树状结构,但可以用各种信息装饰,从而将这些树变成图表。这在形式上和实用上都很方便,并且被编译器和编程系统进一步使用。
因此,从根本上来说,AST就是名称所暗示的一棵树,但是可以携带更多信息。其余的在实现者的选择和旁观者的眼中。是图还是装饰树?但是,基本的AS树很重要,因为这是您在理论和编程上都建立的基础。
请注意,AST与解析树(语法是基于上下文的)不同,后者是由形式语言理论中研究的解析算法产生的。原因是语法的设计受到当时的解析技术的限制,而语法技术本身却受到可用的低计算能力的限制。结果是语法树只是人们自然会考虑的程序结构的受折磨的变体,必须执行进一步的处理而不是基本正式语法分析过程的真正部分,才能获得更干净,更简单的称为AST的版本。
但是,当您要表示歧义句子的所有结构时,计算机上树的表示(无论是否抽象)都会受到一定的限制。特别是,这隐藏了复杂性问题。在从解析树转换为AS树的同时,保留图结构中的歧义也可能是一个问题。但是,如果您对此感到担心,则通常可以用解析树可以用作AST的方式定义具体语法。处理歧义性的非常通用的算法以及当前计算机的功能都允许这样做。
如果使用GLR解析(Generalized LR)进行解析,并且输入的解析不明确(有多种可能的方式来解析输入),则解析的结果可以被认为是解析DAG,而不是解析树。解析DAG紧凑地编码许多可能的解析:多个可能的解析树。
但是,最重要的是,如果您具有上下文无关的语法,并且您的输入字符串是明确可解析的(语法中只有一个派生可生成此输入字符串),并且解析的工作是要产生推导...然后在这些条件下,解析的输出将始终必须是解析树,因为任何与上下文无关的语法的产生都固有地具有树结构。