操作指南:VS2012 "C" 项目 /w Flex & Bison
在 VS2012 中创建一个 "C" 项目,然后添加 Flex 词法分析和 Bison 语法分析功能。
引言
安装新的 Visual Studio 2012 时,我惊讶地发现没有 "C" 项目模板,只有 C++。谷歌搜索也没有找到 C 语言专用模板和具体的示例;C 语言似乎已经过时了……尽管编译器仍然支持它。因此,这里提供了一种从 C++ 模板创建 C 项目的方法。
此外,还讨论了如何为项目设置 Windows 版的 Flex 和 Bison ——用于词法分析和数据流解析的工具。
背景
Lex 和 Yacc 很早就起源于 UNIX 世界。Yacc 代表“另一个编译器编译器”(yet another compiler compiler),Lex 是“词法分析器”(lexical analyzer)。Lex 读取文件或数据流,并将其分解为组成部分,称为标记(tokens)。标记可以是数字、关键字、字符串、标点符号等。Yacc 通常接收这个标记流,根据规则对其进行结构化,然后查找匹配的模式。如果找到匹配项,就会执行相应的操作。这两个工具结合起来,可以比编写数百行传统 C 代码更清晰、更有效地解析输入流并对其进行操作。Lex 和 Bison 的语法非常强大且紧凑。
如今,Flex 和 Bison 是 Lex 和 Yacc 的 GNU 等价物(呵呵!)。然而,它们仍然只是 Unix 平台工具。Win32 世界从未出现过类似的东西。多年来,它们被移植过几次,但需要大量的 GNU 支持库,而且更新频率很低。(我找到的最后一个 Flex 移植版本几乎有十年了!)当然,它太旧了,无法与示例一起使用。
但 SourceForge 上的一些开发者创建了一个名为 WinFlexBison 的软件包。这是为 Win32 移植的现代 Flex 和 Bison 的紧凑、全包版本,并得到定期维护。我们将使用这个软件包。
顺便说一句,WinFlexBison 可以输出 C、C++ 和 Java 代码,但这里只使用 C。
在 VS2012 中创建 Win32 "C" 项目
要在 Visual Studio 2012 中创建 Win32 "C" 项目
1. 创建一个新项目。选择 Win32 C++ 控制台。给它起一个描述性的名称。下一步。
2. 取消选中“使用预编译头文件”复选框,然后选中“创建空项目”复选框。单击完成。
3. 右键单击“源文件”,单击“添加”,然后单击“新建项”。将其命名为 main.c。单击它并将此文本复制进去
#include
int main(void)
{
printf("Press ENTER to close. ");
getchar();
return 0;
}
4. 在左侧的解决方案资源管理器中右键单击主项目,选择“属性”,然后选择“C/C++”,“所有选项”,并将“编译方式”设置为“C 代码”。

5. 按 F5 进行编译和调试。您的“C”项目就完成了!
在 Windows 中使用 Flex 和 Bison
要在 Windows 中使用 Flex 和 Bison,
1. 从 http://sourceforge.net/projects/winflexbison/ 获取 WinFlexBison 并将其解压到有意义的位置,然后将该路径添加到系统路径中。如果您需要有关系统路径的帮助,请参阅此处和此处。关闭任何命令提示符。
2. 在项目中创建以下新文件:Expression.c/.h, Lexer.l/.c/.h, Parser.y/.c/.h
3. 将文件数据从 http://en.wikipedia.org/wiki/GNU_bison 复制到这些文件中(其中一些将保持为空)。将之前的暂停代码合并到实际 main() 函数的末尾。请务必在输入数据时保存所有这些文件,我们将在下一步中使用它们。
4. 打开命令提示符,导航到您的 .Y 和 .L 文件所在目录,然后运行以下命令
Flex 或 Bison 没有错误消息?很好。也可以通过这种方式测试其他设置。这个例子喜欢开启 --wincompat 选项。
5. 尝试构建项目。它很可能会显示一些警告。您需要稍后处理这些警告。
现在开始自动化 .l 和 .y 文件的构建
1. 右键单击 Parser.y -> 属性 -> 将“项类型”设置为“自定义构建工具”。
2. 单击左侧的“自定义构建工具”,然后键入“c:\your-path-to-winflexbison\win_bison parser.y”,替换为实际路径。
3. 将描述更改为“BISON Custom Build Tool”。
4. 将“输出”设置为“parser.h,parser.c”
对 Lexer.l 重复此操作,但命令为“yourpath\win_flex --wincompat lexer.l”,依此类推。
按 F5……搞定!现在去抓虫子吧。:) 您最终应该得到这个
关注点
如果您严格按照本指南(以及 Wikipedia 上的示例未发生更改)进行操作,应该会有两个“错误”。一是“yyerror”会定义两次。这是因为该函数同时出现在 Lexer.l 和 Parser.y 中。解决方案是将其中一个更改为
int yyerror(SExpression **expression, yyscan_t scanner, const char *msg);
另一个问题是 main.c(24): warning C4090: 'function' : different 'const' qualifiers。这相当模糊,但查看该行代码,简单的更改即可解决此问题
SExpression *getAST(char *expr) // was const char, removed const.
源代码
历史
修订 1.0 于 2013.9.11