【发布时间】:2017-03-31 16:45:10
【问题描述】:
我正在尝试使用 parsec 读取 C/C++/java 源文件并对整个文件进行一系列转换。第一阶段删除字符串,第二阶段删除 cmets。 (那是因为你可能会在字符串中得到 /*。)
所以每个阶段都将一个字符串转换为 Either String Error,我想将它们绑定在一起(在 Either 的意义上),以形成整个文件的转换管道。这似乎是一个相当普遍的要求。
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
那么我该怎么做呢?我试过 parserBind 但没有用。
(如果有人关心为什么,我正在尝试做一种简单的解析,我只提取我想要的内容,但避免解析整个语法,甚至不知道它是 C++ 还是 Java。我需要提取的只是所有类和函数的开始和结束行号。所以我设想了一堆预处理阶段,它们只是清除 cmets、#defines/ifdefs、模板前导码和括号内容(因为 for 子句中的分号),然后我会解析 {s 之前的 sn-ps(或因为 typedefs 而在 }s 之后)并通过另一个阶段填充这些 sn-ps 以获取它的类型和名称,然后递归到第二级以获取 java 成员函数.)
【问题讨论】: