Haskell Parsec计算中的执行顺序
我很难弄清楚如何调试用Parsec编写的解析器。最奇怪的是执行的顺序。我有以下代码:Haskell Parsec计算中的执行顺序,haskell,parsec,Haskell,Parsec,我很难弄清楚如何调试用Parsec编写的解析器。最奇怪的是执行的顺序。我有以下代码: import Data.Text (pack) import Debug.Trace import Text.Parsec.Text (Parser) import Text.Parsec material :: Parser MTL material = do name <- many finishLine >> string "newmtl" >> whitespaces
import Data.Text (pack)
import Debug.Trace
import Text.Parsec.Text (Parser)
import Text.Parsec
material :: Parser MTL
material = do
name <- many finishLine >> string "newmtl" >> whitespaces >> manyTill anyChar (try finishLine)
illumCmds <- parseIllum
texMapCmds <- parseTexMaps
let mtl = constructMaterial name illumCmds texMapCmds
traceShow mtl $ return ()
return mtl
parseMTL :: FilePath -> IO [MTL]
parseMTL filepath = do
s <- readFile filepath
case parse (many material) filepath (pack s) of
Left x -> error $ show x
Right x -> return x
loadMTL :: FilePath -> IO ()
loadMTL fp = do
putStrLn $ "Start loading MTL: " ++ show fp
parseMTL fp >>= print
putStrLn $ "Finished."
所以我发现我的程序中有一个错误,我希望通过使用trace
,我可以缩小它的范围(显示thunk将强制对其进行评估,并且它将解决所有以前的解析,直到调用trace
)。然而,我有一些行为,我不太明白。我的输出如下:
... other stuff ...
MTL { ... everything looks good here ... }
... other stuff ...
Loading MTL: filepath.mtl
lobjview.exe: Text.ParserCombinators.Parsec.Prim.many:
combinator 'many' is applied to a parser that accepts an empty string.
# Default material file. Created by Morgan McGuire and released into
# the Public Domain on July 16, 2011.
#
# http://graphics.cs.williams.edu/data
newmtl default
Ns 10.0000
Ni 1.5000
Tr 0 0
illum 2
Ka 1 1 1
Kd 1 1 1
Ks 0.2 0.2 0.2
Ke 0 0 0
map_Kd default.png
所以我的第一个问题是:
- 为什么我的
显示在跟踪
monad的输出之前IO
+RTS-xc
运行它,以查看此错误来源的堆栈跟踪。最好的猜测是:
Text.Parsec.Prim.CAF
--> evaluated by: Lambency.Loaders.MTLLoader.whitespace,
called from Lambency.Loaders.MTLLoader.finishLine.comment,
called from Lambency.Loaders.MTLLoader.finishLine.endMarker,
called from Lambency.Loaders.MTLLoader.finishLine,
对应于此代码的:
whitespace :: Parser Char
whitespace = tab <|> char ' '
whitespaces :: Parser [Char]
whitespaces = many whitespace
finishLine :: Parser ()
finishLine = many (whitespace <|> comment) >> endMarker >> return ()
where
endMarker = endOfLine
comment :: Parser Char
comment = char '#' >> manyTill anyChar (try $ lookAhead endMarker) >> return '_'
你可以发布
endOfLine
的定义,或者源代码的链接吗?这很大程度上取决于你的部分内容--
部分。在您给出的代码中,material
只解析空字符串,因此对其应用many
是一个错误。@JohnLendOfLine
来自。@luqui我不相信它是否依赖于此。我编辑了我的文章以包含完整的代码,只是为了表明它不会只解析空字符串,但我的问题是,我认为这不重要。为什么traceShow
的输出在IO
调用的输出之前正确显示?既然traceShow
的输出是正确的,为什么我的解析器会因为它提供的错误而失败?@Mokosha您的许多调用看起来都没有引发您看到的错误。所以我推测问题在别处。当你提问时,你应该让别人很容易重复你的问题。一点一点地给出部分程序没有帮助。例如,您的示例输出提到加载MTL
,但您的代码片段打印开始加载MTL
。老实说,我不相信你给我们看的和你实际运行的是一致的。
# Default material file. Created by Morgan McGuire and released into
# the Public Domain on July 16, 2011.
#
# http://graphics.cs.williams.edu/data
newmtl default
Ns 10.0000
Ni 1.5000
Tr 0 0
illum 2
Ka 1 1 1
Kd 1 1 1
Ks 0.2 0.2 0.2
Ke 0 0 0
map_Kd default.png