【发布时间】:2012-03-17 02:29:51
【问题描述】:
我想我(大致)了解递归下降解析器(例如 Scala 的解析器组合器)是如何工作的:您使用一个解析器解析输入字符串,然后该解析器为整个输入的每个“部分”调用其他更小的解析器,并且以此类推,直到您到达直接从输入字符串的片段生成 AST 的低级解析器
我也认为我了解 Lexing/Parsing 的工作原理:首先运行词法分析器将整个输入分解为一个扁平的令牌列表,然后运行一个解析器来获取令牌列表并生成一个 AST。
但是,我不明白 Lex/Parse 策略如何处理您如何准确标记某事物取决于之前标记的标记的情况。例如,如果我取一大块 XML:
"<tag attr='moo' omg='wtf'>attr='moo' omg='wtf'</tag>"
递归下降解析器可能会将其分解(每个后续缩进代表父字符串的分解)
"<tag attr='moo' omg='wtf'>attr='moo' omg='wtf'</tag>"
-> "<tag attr='moo' omg='wtf'>"
-> "<tag"
-> "attr='moo'"
-> "attr"
-> "="
-> "moo"
-> "omg='wtf'"
-> "omg"
-> "="
-> "wtf"
-> ">"
-> "attr='moo' omg='wtf'"
-> "</tag>"
然后,单独解析<tag、attr="moo" 等的小型解析器将构建 XML 标记的表示并为其添加属性。
但是,单步 Lex/Parse 如何工作?词法分析器如何知道<tag 和> 之前的字符串必须标记为单独的属性,而> 和</tag> 之间的字符串不需要?它不需要解析器告诉它第一个字符串在标签正文内,而第二种情况在标签正文外吗?
编辑:更改示例以使其更清晰
【问题讨论】:
-
一个词法分析器会产生类似
LEFTANGLE IDENT=tag IDENT=attr EQ STRING=moo IDENT=omg等的东西 -
@SK-logic:编辑问题以澄清。我的困惑是,如果标签主体有一个
attr='moo'outside,词法分析器怎么知道不将其分解为IDENT=tag,而只是将其标记为一个大文本节点?跨度> -
好的,我明白了——它不会用词法分析器将这些东西标记为单个大字符串,你必须解构一个字符串(当然,丢失所有的空格)。
-
您对它的工作原理有错误的概念。状态由递归处理。您的代码将从查看左尖括号开始,然后分支到 ReadTag 方法。 ReadTag 方法会在看到标识符时调用 ReadParameter。因此,您的上下文保存在 ReadTag 方法中。如果从来没有左尖括号,那么标签之外的部分将进入不同的子例程,并且可能在其中被视为文本。这就是递归下降得名的地方。