问题 我如何处理AST中的评论?


我正在使用Parsec编写Delphi代码解析器,我目前的AST数据结构如下所示:

module Text.DelphiParser.Ast where

data TypeName = TypeName String [String] deriving (Show)
type UnitName = String
data ArgumentKind = Const | Var | Out | Normal deriving (Show)
data Argument = Argument ArgumentKind String TypeName deriving (Show)
data MethodFlag = Overload | Override | Reintroduce | Static | StdCall deriving (Show)
data ClassMember = 
      ConstField String TypeName
    | VarField String TypeName
    | Property String TypeName String (Maybe String)
    | ConstructorMethod String [Argument] [MethodFlag]
    | DestructorMethod String [Argument] [MethodFlag]
    | ProcMethod String [Argument] [MethodFlag]
    | FunMethod String [Argument] TypeName [MethodFlag]
    | ClassProcMethod String [Argument] [MethodFlag]
    | ClassFunMethod String [Argument] TypeName [MethodFlag]
     deriving (Show)
data Visibility = Private | Protected | Public | Published deriving (Show)
data ClassSection = ClassSection Visibility [ClassMember] deriving (Show)
data Class = Class String [ClassSection] deriving (Show)
data Type = ClassType Class deriving (Show)
data Interface = Interface [UnitName] [Type] deriving (Show)
data Implementation = Implementation [UnitName]  deriving (Show)
data Unit = Unit String Interface Implementation deriving (Show)

我想保留我的AST数据结构中的注释,我现在正试图弄清楚如何做到这一点。

我的解析器分为lexer和解析器(都是用Parsec编写的),我已经实现了注释令牌的lexing。

unit SomeUnit;

interface

uses
  OtherUnit1, OtherUnit2;

type
  // This is my class that does blabla
  TMyClass = class
  var
    FMyAttribute: Integer;
  public
    procedure SomeProcedure;
    { The constructor takes an argument ... }
    constructor Create(const Arg1: Integer);
  end;

implementation

end.

令牌流如下所示:

[..., Type, LineComment " This is my class that does blabla", Identifier "TMyClass", Equals, Class, ...]

解析器将其转换为:

Class "TMyClass" ...

Class 数据类型没有任何附加注释的方法,因为注释(尤其是块注释)几乎可以出现在令牌流中的任何位置,我必须向AST中的所有数据类型添加可选注释吗?

我如何处理AST中的评论?


7868
2018-05-04 15:27


起源

也可以看看 stackoverflow.com/questions/9392546/... 并检查这些AST是如何定义的。例如。, hackage.haskell.org/package/haskell-src-exts-1.16.0.1/docs/... 在注释中是多态的。 - d8d0d65b3f7cf42


答案:


处理AST上的注释数据的一种合理方法是通过一个额外的类型参数来创建,该参数可以包含您喜欢的任何元数据。除了能够有选择地包含或忽略注释之外,还可以让您在树中包含其他类型的信息。

首先,您将使用额外的参数重写所有AST类型:

data TypeName a = TypeName a String [String]
{- ... -}
data ClassSection a = ClassSection a Visibility [ClassMember a]
{- ... -}

添加会很有用 deriving Functor 对所有这些人来说,也很容易转换给定AST上的注释。

现在,带有注释的AST将具有该类型 Class Comment 或者那种效果。您还可以将其重用于范围分析等其他信息,其中您将当前范围包含在AST的相关部分中。

如果你想一次多个注释,最简单的解决方案是使用一个记录,虽然这有点尴尬,因为(至少现在¹)我们不能轻易地在记录字段上编写代码多态。 (即我们不能轻易地写出“任何带有记录的记录” comments :: Comment 领域”。)

你可以做的另一件好事是使用 PatternSynonyms (可从GHC 7.8获得)有一套模式,就像你当前未注释的AST一样,让你重用现有的case语句。 (为此,您还必须重命名带注释类型的构造函数,以使它们不重叠。)

pattern TypeName a as <- TypeName' _ a as

脚注

¹希望第2部分 恢复重载记录字段提案 当它真正被添加到语言中时,将在这方面提供帮助。


11
2018-05-04 17:38