3

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

4

1 回答 1

4

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

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 进行注释,您可以通过使用 monoid 实例折叠树的任何部分来计算树的跨度,因为该实例Span采用它们的并集(或更具体地说是它们的边界框),即从到a <> b的跨度。(beginRow a, beginCol a) `min` (beginRow b, beginCol b)(endRow a, endCol a) `max` (endRow b, endCol b)

于 2019-12-19T21:14:34.417 回答