haskell - 如何使用 megaparsec 获取 AST 节点的源范围?

标签 haskell megaparsec

我正在尝试为正在解析的某些源文件生成源映射,并且我想获取每个节点的范围。 getSourcePos只给出 start position一个节点(src:line:column)。如何获得它的结束位置?

最佳答案

如果你想为每个词位构造一个这样的源跨度:

data Span = Span SourcePos SourcePos

data Spanned a = Spanned Span a

您可以调用getSourcePos两次,一次在标记的开头,一次在结尾,在消耗任何空格之前,假设您处于词法分析阶段。我过去曾使用过这样的结构来使其更方便:
-- Augment a parser with a source span.
spanned :: Parser (a, SourcePos) -> Parser (Spanned a)
spanned parser = do
  start <- getSourcePos
  (x, end) <- parser
  pure (Spanned (Span start end) x)

-- Consume whitespace following a lexeme, but record
-- its endpoint as being before the whitespace.
lexeme :: Parser a -> Parser (a, SourcePos)
lexeme parser = (,) <$> parser <*> (getSourcePos <* whitespace)

请记住 getSourcePos根据文档,这有点贵,如果我没记错的话,这取决于源文件的大小。

如果 AST 使用 span 进行注释,您可以通过将其与 Span 的 monoid 实例折叠来计算树的任何部分的 span。这需要他们的联合(或更具体地说是他们的边界框),即 a <> b(beginRow a, beginCol a) `min` (beginRow b, beginCol b) 的跨度至(endRow a, endCol a) `max` (endRow b, endCol b) .

关于haskell - 如何使用 megaparsec 获取 AST 节点的源范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59415953/

相关文章:

Haskell:多个字符串之间的所有组合

haskell - 在 Haskell 中内存 IO 计算

validation - Haskell:检查字符串是否为有效数字

haskell - 如何将 MegaParsec "ParseErrorBundle"转换为 "SourcePos"和错误消息的列表

Haskell Megaparsec - 保留字解析为标识符

haskell - 使用 Megaparsec 使用开始和结束符号解析 block 注释

haskell - 类型约束最终变得模棱两可

使用 foldLine 解析多个 block

haskell - Megaparsec:无法解析递归算术字符串

haskell - 如何删除 Haskell (GHC) 中的 "if ... then ... else ..."关键字?