在 Perl 中解析多嵌套条件 C 预处理器语句
Posted
技术标签:
【中文标题】在 Perl 中解析多嵌套条件 C 预处理器语句【英文标题】:Parse multi-nested conditional C-preprocessor statements in Perl 【发布时间】:2014-09-08 23:09:08 【问题描述】:我正在尝试想出一种方法来轻松解析一些 C 头文件。我有三个头文件,File_A1、File_A2 和 File_B。
File_A* 仅包含 #defines
。 #defines
本身可以映射到布尔值、数字数据或像(E && F)
这样的条件语句,其中E
和F
在文件的前面定义。例如:
FILE_A1
#define TRUE 1
#define FALSE 0
#define USERWARE TRUE
#define SECTION_SIZE 2
#define ENGR2_LOAD_ADDRESS 0x6FF020
#define INTEGER_ONLY_SUPPORT FALSE
#define PRESSURE_SENSOR_MIN_KPA_DELTA -50
#define DUMMY_ENGR2_LOAD_ADDRESS 0x92059020
#define FAST_FLUSH_SUPPORT USERWARE
FILE_A2 非常相似。
File_B 在定义方面有点复杂。它包含嵌套的#define 语句,其中许多都被#if...#elif...#endif
包围,因此类似于:
文件_B
#include "File_A1.h"
#include "File_A2.h"
#if (FAST_FLUSH_SUPPORT )
#define MEMORY_BUDGET_FLASH_DIR (12 * 256)
#define MEMORY_BUDGET_FLASH_CFG (15 * 256)
#else //(FAST_FLUSH_SUPPORT )
#define MEMORY_BUDGET_FLASH_DIR (0)
#define MEMORY_BUDGET_FLASH_CFG (0)
#endif //(FAST_FLUSH_SUPPORT )
#define DRAM_OFFSET_FLASH_DIR (DUMMY_ENGR2_LOAD_ADDRESS)
#define DRAM_OFFSET_FLASH_CFG (DRAM_OFFSET_FLASH_DIR + MEMORY_BUDGET_FLASH_DIR)
#define DRAM_OFFSET_FLASH_LOG (DRAM_OFFSET_FLASH_CFG + MEMORY_BUDGET_FLASH_CFG)
#define DRAM_FLASH_CFG_BASE (DRAM_OFFSET_FLASH_CFG + ENGR2_LOAD_ADDRESS)
#define DRAM_FLASH_CFG_SIZE (MEMORY_BUDGET_FLASH_CFG)
如您所见,它可能会有点毛。我想做的是将所有 FILE_B 的#defines
解析为一个评估级别。此外,所有条件都将被处理和删除。 (假设用户软件为 TRUE),
#define MEMORY_BUDGET_FLASH_DIR (12 * 256)
#define MEMORY_BUDGET_FLASH_CFG (15 * 256)
#define DRAM_OFFSET_FLASH_DIR (0x92059020)
#define DRAM_OFFSET_FLASH_CFG (0x92059020 + (12 * 256))
#define DRAM_OFFSET_FLASH_LOG ((0x92059020 + (12 * 256)) + (15 * 256))
#define DRAM_FLASH_CFG_BASE ((0x92059020 + (12 * 256)) + 0x6FF020)
#define DRAM_FLASH_CFG_SIZE ((15 * 256))
如果我能达到这样的程度,那么我可以研究下一步,即评估宏的所有右侧。例如,MEMORY_BUDGET_FLASH_DIR 的计算结果为 3,072。
这些的构建过程漫长而繁琐,涉及数千个文件,因此使用 -E 运行 gcc 并不是最好的解决方案。事实上,它可能是最糟糕的解决方案之一,因为我相信“-E”可以解析所有宏声明,所以我失去了最初的定义。此外,我真正需要的文件只有 File_A1、File_A2 和 File_B,这意味着其他数千个文件在此范围内毫无意义。
我希望找到一种简单的方法来解析这些语句。 我不太清楚如何评估扩展的表达式,也不知道存储所有这些信息的结构是什么。我希望用 Perl 写这个,因为我对它有一些小的经验,比 Python 更多。
任何帮助将不胜感激。
编辑:更新了问题描述以反映真实价值。稍微澄清一下。
【问题讨论】:
这不是很清楚。您在寻找什么最终输出?为什么不能将这三个标头打包成一个简单的 C 测试工具,然后直接调用gcc -E
呢?
@OliCharlesworth 无意义的约束通常表示作业!这实际上是一个有点牵强的小项目。
@soplu:我看到你已经编辑了你的问题,但我仍然读到“FILE_A2 非常相似”。看起来你没有编写规范的习惯。请解释一下这整件事是为了什么,因为我可以想象现实生活中的 C 预处理器可以解决所有这些问题的几种方法。
关键问题是,如果 OP 要处理真正的 C 代码的“数千个文件”,他的头文件中很可能有各种预处理器地狱。 OP 需要强烈说服我们,他需要的东西要少得多,以获得比“获得完整的预处理器”更少的建议,或者可以以比 C 更复杂的方式解析处理器文件的东西。
不确定这是否有帮助,但您可能想看看Coan
【参考方案1】:
在 Perl 中,您可以使用 Marpa::R2 — 一个通用的 BNF 解析器。
This gist 将 FILE_B 的开头从您的 qiestion 解析为一棵树(请参阅评论中的输出)。
希望这会有所帮助。
【讨论】:
这看起来是我收到的两个选项中最有希望的,谢谢。我需要摆弄它,但我认为这应该可行。并感谢您提供一个让我开始的例子。以上是关于在 Perl 中解析多嵌套条件 C 预处理器语句的主要内容,如果未能解决你的问题,请参考以下文章
在批处理文件中,如果满足一个条件而不是周围的 for 循环,如何突破嵌套的 if 语句?