我正在使用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数据结构中的注释,我正在试图找出如何做到这一点.
我的解析器被分解成一个词法分析器和一个解析器(都用Parsec编写),我已经实现了注释标记的词法.
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" ...
类数据类型没有任何方式附加注释,并且由于注释(特别是阻止注释)几乎可以出现在令牌流中的任何位置,我必须向AST中的所有数据类型添加可选注释.
如何处理我的AST中的评论?
解决方法
用于处理AST上注释数据的合理方法是通过可以包含任何您喜欢的元数据来连接一个额外的类型参数.除了能够选择性地包含或忽略评论外,还可以让您在树中包含其他种类的信息.
首先,您将使用额外的参数重写所有AST类型:
data TypeName a = TypeName a String [String] {- ... -} data ClassSection a = ClassSection a Visibility [ClassMember a] {- ... -}
将派生的Functor添加到所有它们也是有用的,使得在给定的AST上转换注释变得容易.
现在有一个AST,留下的评论会有类型“类注释”或者这样的东西.您还可以重复使用此类附加信息,如范围分析,其中将当前范围与AST的相关部分进行比较.
如果您一次想要多个注释,最简单的解决方案就是使用一个记录,尽管这有点尴尬,因为(至少在现在¹)我们不能轻易地在记录字段上编写多态. (即我们不能轻易地写出类型“任何记录与评论:评论字段”.)
您可以做的另一件简单的事情是使用PatternSynonyms
(可从GHC 7.8获得)具有一组模式,与当前未注释的AST一样工作,让您重用现有的案例语句. (为此,您还必须重命名注释类型的构造函数,以使它们不重叠.)
pattern TypeName a as <- TypeName' _ a as
脚注
¹希望第2部分,当它实际上添加到语言时,revived overloaded record fields proposal将有助于这方面.