我使用uu-parsinglib
,但我认为以下问题是解析器组合通用。
让我们考虑以下示例:
我有一个带有组合器pLex
的词法分析器,它产生一个标记列表(类型为MyToken
)。我现在想编写一个解析器,它将使用令牌并构建AST
。
连接词法分析器和解析器的最佳方法是什么?现在我有一个lex
函数:
lex s = parse ( (,) <$> pLex <*> pEnd) (createStr (LineColPos 0 0 0) s)
我应该创建一个函数parse p = ...
吗?如果是,我如何构建它以跟踪词法分析器中的列和行?或者我应该创建一个parserCombinator
,它会以某种方式使用pLex
组合器吗?
答案 0 :(得分:3)
基于表格的解析器需要分离词法分析和解析,因为它们的前瞻能力有限。展望未来,将词法分析与解析器结合起来会破坏状态空间。
基于组合器的方法通常不会遇到这个问题,因为它们通常进行递归下降解析。除非图书馆作者另有说明,否则将这些阶段结合起来并没有什么害处,并且通过分离它们并没有多大帮助。
虽然uu-parsinglib提供了Str
类来抽象不同的类似字符串的输入,但是查看它的定义表明它仍然假设你最终正在读取一个Char序列,无论它们来自String, ByteString,Text等等因此试图解析MyToken流似乎很难。如果您认为需要这样做,Parsec可能是更好的选择。
关于你的字符串实现的问题,组合器采用包含句法结构的字符串式输入,并返回相应的语义值(如果匹配)。在组合器内部,您可以通过组合来自您调用的子组合器的语义值,从输入流和获取直接解析的内容来构建语义值。
因此,您的示例中的'字符串匹配'组合器将在其范围内有一个令牌列表,这要归功于它所做的解析。您可以使用Haskell的全部功能将这些标记组合成一个单独的MyString值,无论以何种方式对您的语言有意义:可能是一个'SplicedString'类型,表示要将哪些值切入其中。
字符串组合器可能由'expression'组合器调用,它可以将MyString值与其他已解析的值组合成MyExpression值。它的组合器一直在返回语义值!
答案 1 :(得分:1)
我认为uu-parsinglib中没有任何内容阻止您使用与Text不同的输入。只有Text(和朋友)才能提供你可能需要的一些功能。如果你看一下较旧的uulib解析器组合器,你会发现一种基于扫描器的方法,它可以和更新的uu-parsinglib一样使用。
如果您想处理大量数据,最好有单独的扫描阶段。错误消息往往提供更多信息。在uulib中你会发现一些支持编写你的扫描仪(大多数语言在某种程度上对词汇结构提出了一些特殊的限制/要求,相当一些工具(失败/需要调整)来创建你的扫描仪(例如越位规则))< / p>