解析错误的自动完成建议

Auto-completion suggestions from parse error

提问人:ttylec 提问时间:10/19/2017 更新时间:10/19/2017 访问量:236

问:

我正在使用 megaparsec 为自定义 jupter 内核编写解析器。我也能够重用解析器来提供补全:从 megaparsec 库生成的自定义错误消息被转换为预期符号列表。这样,每当我更改解析器时,完成都会自动调整。这太棒了。

我唯一挣扎的是如何从可选的解析器中获取信息。下面是说明我想要实现的目标的最小示例:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Applicative
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
import Data.Monoid
import Data.Text (Text)
import Data.Set (singleton)

type Parser = Parsec MyError Text

data MyError = ExpectKeyword Text deriving (Eq, Ord, Show)

lexeme = L.lexeme sc
sc = L.space (skipSome (oneOf [' ', '\t'])) empty empty

-- | Reserved words
rword :: Text -> Parser Text
rword w = region (fancyExpect (ExpectKeyword w)) $
          lexeme (string w *> return w)

fancyExpect f e = FancyError (errorPos e) (singleton . ErrorCustom $ f)

p1 = rword "foo" <|> rword "bar"

p2 = (<>) <$> option "def" (rword "opt") <*> p1

main = do
  putStrLn . show $ parse p1 "" ("xyz" :: Text) -- shows "foo" and "bar" in errors
  putStrLn . show $ parse p2 "" ("xyz" :: Text) -- like above, no optional "opt"

在第一种情况下,解析器失败,我从所有备选方案中获取所有错误的列表。理想情况下,在第二种情况下,我也希望看到失败的可选解析器的错误。

这个例子可以通过删除并创建两个分支来简单地解决:一个有选项,另一个没有。然而,在实际情况下,可选部分是由几个可选部分组成的排列解析器,因此这种技巧是不可行的。option<|>

解析 Haskell megaparsec

评论

1赞 chi 10/19/2017
这很奇怪,因为是定义,所以我不明白为什么像你说的那样制作两个分支会有所帮助,因为它相当于.option x p = p <|> pure xp <|> p <|> pure x
0赞 ttylec 10/20/2017
通过创建两个分支,我的意思是解析器:.自定义错误中的解析器报告它需要“foo”、“bar”或“opt”。虽然只通知“foo”和“bar”,尽管“opt”也可以。p3 = ((<>) <$> rword "opt" <*> p1) <|> p1p2
0赞 ttylec 10/20/2017
但是,您的评论解释了为什么会产生自定义错误:是总是成功的解析器,因此整个解析器不需要任何输入即可成功。这个问题仍然有效:如何优雅地获得可选解析器所期望的内容。optionpureoption
0赞 chi 10/20/2017
是否对您的问题使用/有任何帮助?不一样,但是......label<?>

答: 暂无答案