1.1测试环境

1.1.1 依赖

词法分析单元测试本质上不依赖于其它任何模块,但需要对源程序进行预处理,即在源程序的一开始添加一个换行,并把所有的字母转化为小写,该工作在main.cpp中进行。
词法分析的记号返回值需要用宏进行定义,也可以用YACC编写一个简单的YACC源程序生成yy.tab.cpp和yy.tab.h,里面包含了记号的宏定义。我们采用了后者。所编写的简单YACC程序如下,主要是对记号进行了声明。

  1. %{
  2. #include "main.h"
  3. #include "yacc.tab.h"
  4. extern "C" {
  5. void yyerror(const char *s);
  6. int yyparse();
  7. extern int yylex();
  8. }
  9. %}
  10. %token PROGRAM
  11. %token CONST
  12. %token VAR
  13. %token ARRAY
  14. %token OF
  15. %token PROCEDURE
  16. %token FUNCTION
  17. %token _BEGIN
  18. %token END
  19. %token IF
  20. %token THEN
  21. %token FOR
  22. %token TO
  23. %token DO
  24. %token ELSE
  25. %token REPEAT
  26. %token UNTIL
  27. %token WHILE
  28. %token IDENTIFIER
  29. %token UINUM
  30. %token UFNUM
  31. %token CHAR
  32. %token TYPE
  33. %token ASSIGNOP
  34. %token RELOP
  35. %token ADDOP
  36. %token MULOP
  37. %token NOT
  38. %token RANGEDOT
  39. %start programstruct
  40. %locations
  41. %%
  42. programstruct:
  43. %%
  44. void yyerror(const char *s) {
  45. cout << s << endl;
  46. }

1.1.2 调试输出

如果定义了宏LEXDEBUG,那么就可以输出词法分析程序的调试输出,即输出按顺序输出每一个记号及其属性。具体做法是,在每一个正则表达式的动作中添加如下代码(以标识符为例)

  1. #ifdef LEXDEBUG
  2. cout << "identifier: " << yylval->str << endl;
  3. #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 输入文件

PascalProgram.pas

1.1.5 输出文件

LexOut.txt

1.2测试计划

  • 有针对性的测试每一种词法错误
  • 组合上述词法错误,词法分析程序能否成功处理错误并恢复(有一些词法错误,例如行长度超过限制,会导致词法分析程序直接停止运行)
  • 以一个较复杂的,没有错误的程序作为最终测试