1.1测试环境
1.1.1 依赖
词法分析单元测试本质上不依赖于其它任何模块,但需要对源程序进行预处理,即在源程序的一开始添加一个换行,并把所有的字母转化为小写,该工作在main.cpp中进行。
词法分析的记号返回值需要用宏进行定义,也可以用YACC编写一个简单的YACC源程序生成yy.tab.cpp和yy.tab.h,里面包含了记号的宏定义。我们采用了后者。所编写的简单YACC程序如下,主要是对记号进行了声明。
%{
#include "main.h"
#include "yacc.tab.h"
extern "C" {
void yyerror(const char *s);
int yyparse();
extern int yylex();
}
%}
%token PROGRAM
%token CONST
%token VAR
%token ARRAY
%token OF
%token PROCEDURE
%token FUNCTION
%token _BEGIN
%token END
%token IF
%token THEN
%token FOR
%token TO
%token DO
%token ELSE
%token REPEAT
%token UNTIL
%token WHILE
%token IDENTIFIER
%token UINUM
%token UFNUM
%token CHAR
%token TYPE
%token ASSIGNOP
%token RELOP
%token ADDOP
%token MULOP
%token NOT
%token RANGEDOT
%start programstruct
%locations
%%
programstruct:
%%
void yyerror(const char *s) {
cout << s << endl;
}
1.1.2 调试输出
如果定义了宏LEXDEBUG,那么就可以输出词法分析程序的调试输出,即输出按顺序输出每一个记号及其属性。具体做法是,在每一个正则表达式的动作中添加如下代码(以标识符为例)
#ifdef LEXDEBUG
cout << "identifier: " << yylval->str << endl;
#endif
那么只要在一开始定义宏LEXDEBUG,就可以产生调试输出
另外,一旦遇到词法错误,也会输出词法错误的详细信息。
1.1.3 获取可执行文件
采用如下命令
flex lex.l //编译lex.l,生成lex.yy.c
ren lex.yy.c lex.yy.cpp //将lex.yy.c更名为lex.yy.cpp
bison -vd --debug yacc.y //编译yacc.y,生成yacc.tab.h和yacc.tab.c
ren yacc.tab.c yacc.tab.cpp //将yacc.tab.c更名为yacc.cpp
g++ lex.yy.cpp yacc.tab.cpp main.cpp -o pascal2c.exe
//编译生成可执行文件pascal2c.exe
1.1.4 输入文件
1.1.5 输出文件
1.2测试计划
- 有针对性的测试每一种词法错误
- 组合上述词法错误,词法分析程序能否成功处理错误并恢复(有一些词法错误,例如行长度超过限制,会导致词法分析程序直接停止运行)
- 以一个较复杂的,没有错误的程序作为最终测试