我编写了一个库来将字符串与一组模式进行匹配,现在我可以轻松地将词法扫描器嵌入到 C 程序中。
我知道有许多完善的工具可用于创建词法扫描器(lex 和 re2c,仅列出想到的前两个)这个问题与词法分析器无关,而是关于“扩展”C 语法的最佳方法。词法分析器示例只是一般问题的具体案例。
我可以看到两种可能的解决方案:
- 编写一个预处理器,将带有嵌入式词法分析器的源文件转换为纯 C 文件,并可能转换为要在编译中使用的一组其他文件。
- 编写一组 C 宏来以更易读的形式表示词法分析器。
我已经做了这两个,但问题是:“根据以下标准,你认为哪一个更好?”
- 可读性。词法分析器逻辑应该清晰易懂
- 可维护性。查找和修复错误不应该是一场噩梦!
- 干扰构建过程。预处理器在构建过程中需要一个额外的步骤,预处理器必须在路径中等等。
换句话说,如果你必须维护或编写一个使用这两种方法之一的软件,哪一种会让你失望更少?
例如,以下是针对以下问题的词法分析器:
- 对所有数字求和(可以是十进制形式,包括像 1.3E-4.2 这样的指数形式)
- 跳过字符串(双引号和单引号)
- 跳过列表(类似于 LISP 列表: (3 4 (0 1)() 3) )
- 在遇到单词 end(大小写无关)或缓冲区末尾时停止
在两种风格中。
/**** SCANNER STYLE 1 (preprocessor) ****/
#include "pmx.h"
t = buffer
while (*t) {
switch pmx(t) { /* the preprocessor will handle this */
case "&q" : /* skip strings */
break;
case "&f<?=eE>&F" : /* sum numbers */
sum += atof(pmx(Start,0));
break;
case "&b()": /* skip lists */
break;
case "&iend" : /* stop processing */
t = "";
break;
case "<.>": /* skip a char and proceed */
break;
}
}
/**** SCANNER STYLE 2 (macros) ****/
#include "pmx.h"
/* There can be up to 128 tokens per scanner with id x80 to xFF */
#define TOK_STRING x81
#define TOK_NUMBER x82
#define TOK_LIST x83
#define TOK_END x84
#define TOK_CHAR x85
pmxScanner( /* pmxScanner() is a pretty complex macro */
buffer
,
pmxTokSet("&q" , TOK_STRING)
pmxTokSet("&f<?=eE>&F" , TOK_NUMBER)
pmxTokSet("&b()" , TOK_LIST)
pmxTokSet("&iend" , TOK_END)
pmxTokSet("<.>" , TOK_CHAR)
,
pmxTokCase(TOK_STRING) : /* skip strings */
continue;
pmxTokCase(TOK_NUMBER) : /* sum numbers */
sum += atof(pmxTokStart(0));
continue;
pmxTokCase(TOK_LIST): /* skip lists */
continue;
pmxTokCase(TOK_END) : /* stop processing */
break;
pmxTokCase(TOK_CHAR) : /* skip a char and proceed */
continue;
);
如果有人对当前的实现感兴趣,代码在这里:http ://sites.google.com/site/clibutl 。