我希望在使用Parsec解析时获得结束标记位置。
例如,如果我按以下方式使用identifier
组合器:
test = do
start <- getPosition
result <- identifier
end <- getPosition
end
不会指向标识符的末尾。它将指向下一个标记(跳过空格)。
我可以编写自己的identifier
组合子以在跳过空格之前获得结束位置,但我想知道在Parsec中是否有任何已经这样做的事情。
有没有办法用Parsec获得组合子的最终位置?
答案 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;的一部分,然后像往常一样跳过空格。然后,您可以从用户状态检索结束位置。