gpt4 book ai didi

haskell - 遇到错误后继续lex

转载 作者:行者123 更新时间:2023-12-02 15:44:09 25 4
gpt4 key购买 nike

我正在大学学习编译器类(class)。我选择使用 Haskell + Parsec 来做这个项目。词法分析器和解析器需要分开。我使用 Parsec 将字符串转换为标记列表,然后将其传递到另一个 Parsec 解析器,该解析器将标记列表转换为 AST。

问题是词法分析器应该继续尝试词法分析,即使出现错误也是如此。为了尝试做到这一点,我向我的 Token 数据类型引入了一个表示“意外 token ”的 token ,并尝试在代码中添加 <|>意外,以便在发生错误时生成此 token 。这是很多样板文件,而且也很难推理出将它们放置在哪里。

我的首选解决方案是以某种方式让 Parsec 自动执行此操作:如果出现 ParseError,则在该位置生成意外标记,并稍后继续解析一个位置。我该怎么做?

这是我现在拥有的一些代码的片段:http://lpaste.net/8144414997276000256由于某种原因,即使意外 token 应该捕获未处理的情况,我仍然会收到解析错误。

最佳答案

看起来您应该能够摆脱一个额外的意外术语。我假设您有一个看起来像这样的 token 类型:

token' =  number
<|> identifier
<|> ...

我可能会让每个标记(数字标识符...等)管理自己的空白:

number :: Parser Token
number = Number . read <$> many1 digit <* spaces

为什么不在本文末尾添加额外的意想不到的术语作为包罗万象的内容?

token' =  number
<|> identifier
<|> ...
<|> unexpected'

让它消耗一个字符。为了获得更好的错误消息,您甚至可以在值中包含该字符。然后,当您使用它创建列表时,您的词法分析器不知道如何处理每个字符,您将获得一个Unexpected值。

unexpected' :: Parser Token
unexpected' = Unexpected <$ anyChar

最后,整个 lex 只是一个many token'。在我的测试中,这可以很好地处理中间的无效字符。

*Main> parse (many token') "<foo>" "1 2 abc ~ ~def"
Right [Number 1,Number 2,Identifier "abc",Unexpected,Unexpected,Unexpected,Identifier "def"]

需要记住的一件事是,Parsec 默认情况下不会回溯。这意味着如果解析在 token 中部分失败,它不会返回并尝试意外:您只会得到一个错误。要启用回溯,您必须在可能出错的解析器上使用 try。例如,如果 identifier 需要两个字符:

identifier :: Parser Token
identifier = Identifier <$> liftA2 (:) letter (many1 alphaNum) <* spaces

然后它可能会在途中失败并且不会回溯。但如果你将它包装在 try 中,它应该可以工作:

token' =  number
<|> try identifier
<|> ...

try 的问题是,如果您不小心,它可能会减慢您的代码速度。但是,如果您不介意速度变慢,则只需在各处添加 try 并进行大量回溯即可摆脱困境!

关于haskell - 遇到错误后继续lex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25813671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com