问题描述
在解析器组合器库(如Haskell的Parsec)中编写解析器时,通常有两个选择:- 编写一个词法分析器来分割
字符串
输入到标记,然后在[标记]
- 上直接执行解析在
字符串
上写入解析器组合器
第一种方法通常看起来有意义很多解析输入可以理解为由空格分隔的标记。
在其他地方,我看到有人建议不要标记化(或扫描或 lexing ,有人称之为),简单地被引用为主要原因。
lexing和不做的一般权衡是什么它是什么?
最重要的区别是lexing会翻译您的输入域。 >一个很好的结果就是 你没有我已经考虑过空白了。在一个直接的(非lexing)解析器中,你必须在允许空格的地方撒上
space
解析器,这很容易忘记,并且它会混乱你的代码if无论如何,空格必须将所有的所有分开。
然而,如果您确实执行了lexing,您会遇到问题 $ b 您不能在
String
上使用公共分析器 - 例如用库函数 parseFloat :: Parsec String s Float
(对字符串输入流进行操作)解析数字时,必须执行类似于 takeNextToken :: TokenParser String
和执行
parseFloat
解析器,检查解析结果(通常 ErrorMessage a
)。这对于编写和限制可组合性来说很混乱。 SourcePos
值)。
错误报告通常较差。运行字符串hello*>空间*> float
在错误的输入如hello4
上会精确地告诉你在 hello $之后缺少空白c $ c>,而词法分析器声称已找到
无效标记
。
许多人认为是原子单元并被词法分隔的事实上对于词法分析器来说确实是非常太难了。以字符串文字为例 - 突然hello world
不是两个标记hello
和世界
了(但是 only ,当然,如果引号没有转义,比如 \
) - while这对解析器来说是非常自然的,它意味着复杂的规则和对于词法分析器的特殊情况。
字符串
中的双精度,导出它,其余的人可以使用它;它们不能首先运行您的(专用)标记器。 当你开发解析语言时,使用词法分析器可能会导致你做出早期决策,修复之后可能需要更改的东西。例如,假设你定义了一种包含 Float
标记的语言,在某些时候,你想引入负文字( -3.4
和 - 3.4
) - 由于词法分析器的原因,这可能是不可能的将空白解释为令牌分隔符。使用仅解析器的方法,您可以保持更灵活,更轻松地更改您的语言。这并不令人惊讶,因为解析器是一个更复杂的工具,它本身编码规则。
最后,词法分析器只是一个简单化的解析器 - if无论如何,你需要一个解析器,将它们合并为一个。
这篇关于在使用像Parsec这样的解析器组合器库时,我应该使用词法分析器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!