Haskell:Parsec:整个文件的转换器流水线



我正在尝试使用parsec读取C/C++/java源文件并对整个文件进行一系列转换。第一阶段删除字符串,第二阶段删除注释。(这是因为您可能会在字符串中得到/*。

因此,每个阶段都将一个字符串转换为任一字符串错误,我想将它们绑定(在任一意义上)在一起以对整个文件进行转换管道。这似乎是一个相当普遍的要求。

import Text.ParserCombinators.Parsec
commentless, stringless :: Parser String
stringless = fmap concat ( (many (noneOf """)) `sepBy` quotedString ) 
quotedString = (char '"') >> (many quotedChar) >> (char '"')
quotedChar = try (string "\"" >> return '"' ) <|> (noneOf """)  
commentless = fmap concat $ notComment `sepBy` comment
notComment = manyTill anyChar (lookAhead (comment <|> eof))
comment = (string "//" >> manyTill anyChar newline >> spaces >> return ()) 
<|> (string "/*" >> manyTill anyChar (string "*/") >>  spaces >> return ())

main =
do c <- getContents
case parse commentless "(stdin)" c of -- THIS WORKS
--     case parse stringless "(stdin)" c of -- THIS WORKS TOO    
--     case parse (stringless `THISISWHATIWANT` commentless) "(stdin)" c of 
Left e -> do putStrLn "Error parsing input:"
print e
Right r -> print r

那么我该怎么做呢?我尝试了解析器绑定,但它不起作用。

(如果有人关心为什么,我正在尝试做一种轻解析,我只是提取我想要的东西,但避免解析整个语法,甚至不知道它是C++还是Java。我需要提取的只是所有类和函数的开始和结束行号。所以我设想了一堆预处理阶段,这些阶段只是清除注释、#defines/ifdefs、模板序言和括号的内容(因为 for 子句中的分号),然后我将解析 {s 前面的片段(或后面的 }s 因为 typedefs),并将这些片段填充到另一个阶段,以获得它的类型和名称, 然后递归到第二级以获取 Java 成员函数。

你需要绑定Either Error,而不是Parser。您需要将绑定移动到parse之外,并使用多个parse

parse stringless "(stdin)" input >>= parse commentless "(stdin)"

可能有比你正在使用的更好的方法,但这会做你想要的。

最新更新