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

How to get source range of AST nodes using megaparsec?

我正在尝试为我正在解析的某个源文件生成一个源映射,我想获取每个节点的范围。 getSourcePos only gives the 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 的幺半群实例折叠它,它采用它们的并集(或更具体地说是它们的边界框) ,即 a <> b 是从 (beginRow a, beginCol a) `min` (beginRow b, beginCol b)(endRow a, endCol a) `max` (endRow b, endCol b) 的范围。