词法分析器和解析器在理论上真的有那么不同吗?
讨厌正则表达式似乎很时髦:编码恐怖,另一篇博文。
然而,流行的基于词法分析的工具:pygments、geshi或prettify都使用正则表达式。他们似乎对任何事情都…
什么时候词法足够,什么时候需要 EBNF?
有没有人将这些词法分析器生成的令牌与 bison 或 antlr 解析器生成器一起使用?
解析器和词法分析器的共同点:
这通常是真正的区别所在。有关更多信息,请参见下文。
词法分析器通过将 词 位(来自输入的符号字符串)分类为特定 标记 来附加意义。例如,所有这些词位:*, ==, <=,^将被 C/C++ 词法分析器归类为“运算符”标记。
*
==
<=
^
[number][operator][number]
[id][operator][id]
[id][operator][number][operator][number]
当词法分析器识别出构成正确数字的字符序列时,它可以将其转换为二进制值并与“数字”标记一起存储。
词法分析器产生 标记 ,它们是它们识别的 常规语言的 句子。 每个标记都可以有一个内部语法(尽管是 3 级,而不是 2 级),但这对于输出数据和读取它们的数据并不重要。 __
[TXT][TAG][TAG][TXT][TAG][TXT]...
如您所见,解析器和分词器有很多共同点。一个解析器可以是另一个解析器的分词器,它将其输入记号读取为它自己的字母表中的符号(记号只是某些字母表的符号),就像来自一种语言的句子可以是其他一些更高级别的字母符号一样语言。例如,如果*和-是字母表的符号M(作为“莫尔斯电码符号”),那么您可以构建一个解析器,将这些点和线的字符串识别为莫尔斯电码中编码的字母。“摩尔斯电码”语言中的句子可能是其他解析器的 标记 ,这些 标记 是其语言的原子符号(例如“英语单词”语言)。这些“英语单词”可能是一些理解“英语句子”语言的高级解析器的标记(字母表的符号)。而 所有这些语言的不同之处仅在于语法的复杂性 。而已。
-
M
那么这些“乔姆斯基的语法水平”到底是怎么回事?好吧,诺姆乔姆斯基根据语法的复杂性将语法分为四个级别:
它们使用正则表达式,也就是说,它们只能由字母符号 ( a, b)、它们的连接符号 ( ab, aba, bbbetd.) 或替代符号 (例如a|b) 组成。 它们可以实现为有限状态自动机 (FSA),如 NFA(非确定性有限自动机)或更好的 DFA(确定性有限自动机)。 常规语法无法处理 嵌套语法 ,例如正确嵌套/匹配的括号(()()(()()))、嵌套的 HTML/BBcode 标记、嵌套块等。这是因为处理它的状态自动机应该有无限多的状态来处理无限多的嵌套级别。
a
b
ab
aba
bbb
a|b
(()()(()()))
它们的语法树中可以有嵌套的、递归的、自相似的分支,因此它们可以很好地处理嵌套结构。 它们可以实现为带有堆栈的状态自动机。此堆栈用于表示语法的嵌套级别。在实践中,它们通常被实现为自上而下的递归下降解析器,它使用机器的过程调用堆栈来跟踪嵌套级别,并对其语法中的每个非终端符号使用递归调用的过程/函数。 但是它们无法处理 上下文相关的 语法。例如,当您有一个表达式时x+3,在一个上下文中,这x可能是一个变量的名称,而在其他上下文中,它可能是一个函数的名称等。
x+3
x
也称为递归可枚举文法。