2

我在做学生研究项目时遇到了一个问题。我是一名电气工程专业的学生,​​但我的项目与理论计算机科学有一定的关系:我需要解析大量 pascal 源代码文件以获取类型定义和常量,并可视化所有出现的情况。类型定义递归地分布在各种文件中,即在文件 x 中有类型 a = byte,在文件 y 中有一个记录(结构)b,它包含类型 a,然后在文件 z 中甚至还有一个类型 c,即b 类型的数组。到目前为止,我的想法是了解编译器的构造,因为编译器必须解析所有类型定义并将它们分解为元素类型。

所以,我在两本书(其中一本甚至是帕斯卡的发明者写的)中读到了关于编译器构造的内容,但是我缺乏太多理论计算机科学的基础知识,以至于我一个人花了一周的时间才完成了一半. 到目前为止,我学到的是,要实现我的目标,词法分析器和解析器就足够了。由于这个软件只是整个项目中非常聪明的一部分,我不能花太多时间在它上面,所以我开始尝试使用 flex,后来又使用了 antlr。

我的希望是,只解析类型定义是一项如此简单的任务,我可以只使用扫描仪来完成它并让它做一些解析器的工作:pascal 文件由 5 个主要部分组成,每个部分都是可选的: 带有注释的标头、一个 const 部分、一个类型部分、一个 var 部分和(至少在某些情况下)一个代码部分。每个部分都有一个开始标识符,但没有明确的结束标识符。所以我开始搜索类型和常量部分(TYPE,CONST)的开头,丢弃其他所有内容。在 flex 中,这相当容易,因为它允许“开始条件”。它们可以用作各种状态,如“INITIAL”、“TYPE-SECTION”、“CONST-SECTION”和“COMMENT”,每个状态都有不同的规则。我想用以下语法“=”从扫描仪中取回一个字符串。AuEingangsBool_t {PCMON} = MAX_AuEingangsFeld;. 扫描器无法使用正则表达式提取此类类型定义。

我的下一步是使用扫描仪和解析器正确执行此操作,因此我搜索了解析器生成器并找到了 antlr。由于我还是用 C# 编写了这个工具,所以我决定也使用它的扫描仪生成器,这样我就不必在不同的程序之间进行通信。现在我遇到了以下问题:AFAIK,antlr 不像 flex 那样支持“开始条件”。这意味着,我必须扫描整个文件(好吧,评论仍然被丢弃)并获得很多不必要的(和错误的)标记。因为我不使用整个帕斯卡语法的规则,所以扫描器会将帕斯卡语法的大多数关键字识别为用户标识符,并且解析器会唠叨所有那些不适合类型和常量定义的标记系列

现在,最后我的问题是:你们中的任何人都可以告诉我,哪种方法可以引导我的项目?是否可以使用 antlr 仅扫描部分源文件?或者我必须为此目的将 flex 与 antlr 连接起来吗?我可以告诉 antlr 的解析器忽略不在 const 或 type 部分中的每个标记吗?这些工具对我的任务来说是否太强大了,我应该编写自己的例程吗?

4

2 回答 2

2

您最好为 Pascal 找到一个编译器,然后简单地修改以报告您想要的信息。大概有这样的 Pascal 编译器,并且通常可以获得此类编译器的源代码。

否则,您基本上需要构建一个解析器。构建词法分析器,然后对产生的词位进行修改,本质上是通过临时方法构建一个糟糕的解析器。ANTLR 是个不错的选择;您可以很容易地定义词位(包括获取和忽略评论的方法),尤其是对于较旧的 Pascal 方言。您需要针对所需类型信息的良好 BNF 规则,并将这些规则转换为解析器生成器。你可以做些什么来最小化工作,就是在你不关心的语言部分的规则上作弊。例如,您可以为赋值语句编写一个准确的子语法。由于您不关心它们,因此您可以编写一个草率的子语法,将赋值语句视为以标识符开头的任何内容,后跟任意其他标记,并以分号结尾。这种文法称为“岛文法”;只有在需要准确的地方才准确。

我不知道递归位。您是否有理由不能单独处理每个文件?答案可能取决于您想了解每种类型声明的哪些信息,如果您深入了解,您可能需要一个符号表以及一个岛解析器。解析器生成器对此没有任何帮助。

于 2013-02-20T15:00:19.417 回答
0

首先,在其他块中可以有 type 和 const 块(过程,在以后的 Delphi 版本中还有类)。

此外,我不完全确定您实际上可以简单地扫描 const 令牌,然后开始解析。在最常见的(Borland)帕斯卡方言中,Const 也用于其他目的。某些关键字可以在不同的上下文中重用,如果您不解析全局块结构,而只在特定位置查找 const 和 type 您将错误地从那里开始解析。

一个基本问题当然是评论。扫描程序会尽早删除评论,并且不会进一步关注它们。您可能必须设置扫描仪,以便将注释作为字段附加到相邻的标记(与之前的标记相关联或将它们保存到某个标记之后)。

至于antlr vs flex,没有线索。我在解析 Pascal 方面有一些小经验的唯一解析器生成器是 Coco/R(Wirthians 流行的解析器生成器),但总的来说,我(和许多 Pascal 人)更喜欢手工编码。

于 2013-02-20T11:48:41.560 回答