我在做学生研究项目时遇到了一个问题。我是一名电气工程专业的学生,但我的项目与理论计算机科学有一定的关系:我需要解析大量 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 部分中的每个标记吗?这些工具对我的任务来说是否太强大了,我应该编写自己的例程吗?