获得Parsec的最终位置

时间:2016-01-10 20:38:23

标签: haskell parsec

我希望在使用Parsec解析时获得结束标记位置。

例如,如果我按以下方式使用identifier组合器:

test = do
    start <- getPosition
    result <- identifier
    end <- getPosition

end不会指向标识符的末尾。它将指向下一个标记(跳过空格)。

我可以编写自己的identifier组合子以在跳过空格之前获得结束位置,但我想知道在Parsec中是否有任何已经这样做的事情。

有没有办法用Parsec获得组合子的最终位置?

1 个答案:

答案 0 :(得分:1)

如果您的意思是来自identifier的{​​{1}},我认为这很容易。 Text.Parsec.Token是使用identifier

定义的
lexeme

identifier = lexeme $ try $ do{ name <- ident ; if (isReservedName name) then unexpected ("reserved word " ++ show name) else return name } 使用空格:

lexeme

这意味着当您从lexeme p = do{ x <- p; whiteSpace; return x } 获得结果时,标识符的结束位置将丢失。

我认为没有优雅的解决方案。一个丑陋的问题是从identifier复制makeTokenParser的定义并更改其Text.Parsec.Token的定义,以便它不会跳过空格。然后你就可以拥有:

lexeme

当然,现在你需要小心,因为解析器不再跳过空格。另一种方法是让myMakeTokenParser :: (Stream s m Char) => GenLanguageDef s u m -> GenTokenParser s u m myMakeTokenParser languageDef = TokenParser{ identifier = identifier , reserved = reserved ... lexeme p = p ... } lexer = myMakeTokenParser haskellDef identifier' = identifier lexer test = do start <- getPosition result <- identifier' end <- getPosition return (result, (start, end)) main = parseTest test "abc def " > :main ("abc",((line 1, column 1),(line 1, column 4))) 记录内部解析器末尾的位置(例如lexeme)作为&#34;用户状态&#34;的一部分,然后像往常一样跳过空格。然后,您可以从用户状态检索结束位置。