对于OpenMP/C的词法扫描器需要处理C语言单词和OpenMP/C制导指令,编译器的词义分析的关键是*.I文件(后缀为I的文件,是字母I,不是数字1)。*.I文件经过flex工具(lex的GNU版本为flex)产生出*.yy.c文件,经过gcc编译后可以生成一个可执行文件进行分析。
OpenMP/C下的这个*.I文件与普通C语言的词义分析不同的是需要区别出OpenMP和C的扫描区域,其主要分成三个部分:
(1)全局声明段。全局声明段主要是分为两个部分,一个部分是开头的6个标记:
D:[0-9] 数字
L:[a-zA-Z_] 字符
H:[a-fA-F0-9] 十六进制数
E:[Ee][+-]?{D}+ 指数形式的浮点数
FS:(f|F|lL) 浮点类型
IS:(u|U|l|L) 整形类型
另一个是“%{ %}”之间的C语言声明,其中包括一个头文件,宏定义,变量的定义,初始规则。
这里的初始规则可以通过函数实现,将文件扫描位置进行初始化,变量start_token用于记录词法分析得初始规则,最后用%%表示C的声明结束,Lex文件的第一段声明部分结束,第二段的开始
(2)模式匹配规则
发现有#pragma omp或#pragma omp threadprivate就说明有OpenMP编译制导指令,此时将on_omp_line和_has_omp置为1,并返回omp符号。这些符号都是在头文件“parser.h”中,第一段已经有过声明。on_omp_line就是用来区别OpenMP与C的公共符号,其它一些匹配还有标识符,类型说明符,操作符,变量等就返回相应的符号编号
PS:当OpenMP的编译制导行的结尾处出现换行符,那么on_omp_line将被置为0,So,编译指令不能跨行。
最后,再以%%结束第二段,开始第三段
(3)自定义函数段(个人这么命名)
这段主要就是实现一些函数,比如sharp()忽略“#”开头的行,gobbleline()忽略“//......”注释行等等
PS:如果编译的时候不加上-ll,还需要加入main函数和yywrap(),main函数中调用yylex()进行词义分析
PPS:对于yywrap函数,实现形式如下:
int yywrap()
{
return 1;
}
一般在函数的末尾调用,返回1停止解析。