与百万秒差距解析后Errorbundles

时间:2019-01-29 22:05:59

标签: haskell megaparsec

我目前在百万秒差距工作的解析器,在那里我建立我的程序的AST。我现在想要做我的AST一些除草作业,同时能够使用同一种非常错误的语法分析器。虽然这个阶段是分析后,如果有这样做的百万秒差距一般做法我不知道。我是否可以提取每行和注释(用于捆绑销售商品)并将其添加到AST中的每一项中?人们还有其他方法可以解决这个问题吗?

在提前道歉,如果这听起来开放式的,但我想主要是有一些比获得的行号,并创建自己捆绑更好的想法。我还是新来的Haskell,所以我一直无法通过所有的源代码正常浏览。

1 个答案:

答案 0 :(得分:0)

megaparsec开发人员here回答了这个问题。

总而言之,解析器具有一个getOffset函数,该函数返回当前的char索引。您可以将其与开头的PosState一起使用,以创建一个错误包,以后可以漂亮地打印出来。

我有一个示例项目within the github thread,并再次粘贴到这里:

module TestParser where

import           Data.List.NonEmpty as NonEmpty
import qualified Data.Maybe         as Maybe
import qualified Data.Set           as Set
import           Data.Void
import           Parser
import           Text.Megaparsec

data Sample
  = Test Int
         String
  | TestBlock [Sample]
  | TestBlank
  deriving (Show, Eq)

sampleParser :: Parser Sample
sampleParser = do
  l <- many testParser
  return $ f l
  where
    f []  = TestBlank
    f [s] = s
    f p   = TestBlock p

testParser :: Parser Sample
testParser = do
  offset <- getOffset
  test <- symbol "test"
  return $ Test offset test

fullTestParser :: Parser Sample
fullTestParser = baseParser testParser

testParse :: String -> Maybe (ParseErrorBundle String Void)
testParse input =
  case parse (baseParser sampleParser) "" input of
    Left e -> Just e
    Right x -> do
      (offset, msg) <- testVerify x
      let initialState =
            PosState
              { pstateInput = input
              , pstateOffset = 0
              , pstateSourcePos = initialPos ""
              , pstateTabWidth = defaultTabWidth
              , pstateLinePrefix = ""
              }
      let errorBundle =
            ParseErrorBundle
              { bundleErrors = NonEmpty.fromList [TrivialError offset Nothing Set.empty]
                            -- ^ A collection of 'ParseError's that is sorted by parse error offsets
              , bundlePosState = initialState
                            -- ^ State that is used for line\/column calculation
              }
      return errorBundle

-- Sample verify; throw an error on the second test key
testVerify :: Sample -> Maybe (Int, String)
testVerify tree =
  case tree of
    TestBlock [_, Test a _, _] -> Just (a, "Bad")
    _                          -> Nothing

testMain :: IO ()
testMain = do
  testExample "test test test"
  putStrLn "Done"

testExample :: String -> IO ()
testExample input =
  case testParse input of
    Just error -> putStrLn (errorBundlePretty error)
    Nothing    -> putStrLn "pass"

某些部分来自其他文件,但重要的部分在代码中。