前言
最近在学校的专业课《编译原理》学习LEX和YACC,课程的环境是在visual studio2022或者visual studio2019中配置的,然而博主遇见的问题是.l和.y文件生成解决方案时老是报错MSB372问题。项目编译结果时好时坏,并且只要把项目关闭后重新打开就彻底完蛋了!在不断的重新创建项目中博主参考网上其他人使用vscode配置flex&bison以及自己的实践后,写下这篇文章向大家分享以下我的成果。
准备工作
VSCode插件:
- C/C++ Extension Pack
- C/C++
- C/C++ Themes
- CMake Tools
- CMake IntelliSence
- LEX(lex and flex syntax highlighting)
- Bison(bison and yacc syntax highlighting)
C/C++编译环境:
- MSYS2 官网地址
LEX&YACC 下载地址
MSYS2的配置
MSYS2下载后,进行安装,安装目录选择自己习惯的Windows盘符。
从开始菜单运行“MSYS2 MSYS”。使用以下命令更新其余基本软件包pacman -Su

安装一些工具和 mingw-w64 GCC包
pacman -S --needed base-devel mingw-w64-x86_64-toolchain`
通过pacman安装适用于MSYS2的CMake包
pacman -S mingw-w64-x86_64-cmake
找到安装MSYS2的目录,把以下路径,例如安装到C盘:path = C:\msys64\mingw64\bin添加到环境变量中。
win11的环境变量:
- 打开“设置”
- 找到“系统”
- 找到“系统信息”
- 找到“高级系统设置”
- 找到“系统属性”下的“高级“属性下的”环境变量“(在右下角)
- 找到”Path”
- 点击”编辑”,点击“新建”,粘贴路径,点击“确定”
- 返回上级点击“确定”
- 再次返回上级点击“应用”,然后“确定”
在Windows的cmd或者powershell中运行验证:
gcc --version
gcc.exe (Rev1, Built by MSYS2 project) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gdb --version
GNU gdb (GDB) 15.2
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
cmake --version
cmake version 3.30.5
CMake suite maintained and supported by Kitware (kitware.com/cmake).
若显示版本号,则安装成功
LEX&YACC的配置
win_flex_bison下载好之后,解压。
在你准备写代码的地方创建一个文件夹,比如:flex_bison.
然后在该目录下创建以下目录:
flex_bison
│ CMakeLists.txt(项目配置文件,必要)
│
├─build(编译调试目录,必要)
│
├─src(源文件存放目录,必要)
│ lex_prog1.l(示例)
│ lex_prog2.l
│ yacc_prog1.y(示例)
│ yacc_prog2.y
│
├─tools(win_flex_bison-latest里的文件存放路径,必要)
│ FlexLexer.h
│ win_bison.exe
│ win_flex.exe
│ └──tools\data(win_flex_bison-latest里的data目录)
把win_flex_bison-latest里的data目录和FlexLexer.h,win_bison.exe,win_flex.exe文件粘贴到flex_bison的tools目录下。
然后是核心文件CMakeLists.txt的编写,代码如下:
cmake_minimum_required(VERSION 3.10)
project(flex_bison C) # 修改项目名称以反映多程序特性
# 工具路径配置
set(FLEX_EXECUTABLE "${CMAKE_SOURCE_DIR}/tools/win_flex.exe")
set(BISON_EXECUTABLE "${CMAKE_SOURCE_DIR}/tools/win_bison.exe")
# 收集所有生成的可执行目标
set(ALL_TARGETS "")
# 处理所有flex词法分析程序(.l文件)
file(GLOB LEX_PROGRAMS "${CMAKE_SOURCE_DIR}/src/*.l")
foreach(lex_file ${LEX_PROGRAMS})
get_filename_component(prog_name ${lex_file} NAME_WE)
# 为每个lex程序创建独立构建目录
set(lex_output_dir "${CMAKE_CURRENT_BINARY_DIR}/flex/${prog_name}")
file(MAKE_DIRECTORY ${lex_output_dir})
# 生成词法分析代码
add_custom_command(
OUTPUT "${lex_output_dir}/lex.yy.c"
COMMAND ${FLEX_EXECUTABLE}
--wincompat
--outfile="${lex_output_dir}/lex.yy.c"
"${lex_file}"
DEPENDS "${lex_file}"
COMMENT "[WIN] Building LEX program: ${prog_name}"
)
# 创建独立可执行文件
add_executable(${prog_name}_lex
"${lex_output_dir}/lex.yy.c"
)
target_include_directories(${prog_name}_lex PRIVATE ${lex_output_dir})
list(APPEND ALL_TARGETS ${prog_name}_lex)
endforeach()
# 处理所有bison语法分析程序(.y文件)
file(GLOB YACC_PROGRAMS "${CMAKE_SOURCE_DIR}/src/*.y")
foreach(yacc_file ${YACC_PROGRAMS})
get_filename_component(prog_name ${yacc_file} NAME_WE)
# 为每个yacc程序创建独立构建目录
set(yacc_output_dir "${CMAKE_CURRENT_BINARY_DIR}/bison/${prog_name}")
file(MAKE_DIRECTORY ${yacc_output_dir})
# 生成语法分析代码
add_custom_command(
OUTPUT
"${yacc_output_dir}/yacc.tab.c"
"${yacc_output_dir}/yacc.tab.h"
COMMAND ${BISON_EXECUTABLE}
-o "${yacc_output_dir}/yacc.tab.c"
--defines="${yacc_output_dir}/yacc.tab.h"
"${yacc_file}"
DEPENDS "${yacc_file}"
COMMENT "[WIN] Building YACC program: ${prog_name}"
)
# 创建独立可执行文件
add_executable(${prog_name}_yacc
"${yacc_output_dir}/yacc.tab.c"
)
target_include_directories(${prog_name}_yacc PRIVATE ${yacc_output_dir})
list(APPEND ALL_TARGETS ${prog_name}_yacc)
endforeach()
# 添加默认构建目标
add_custom_target(build_all ALL DEPENDS ${ALL_TARGETS})
文件示例
编写你的lex(.l)和yacc(.y)文件,给大家2个示例:
LEX
主要功能是读取输入文本,逐行处理,并为每一行添加行号后输出。
%{
#include <stdio.h>
int lineno = 1;
%}
line ^(.*)\n
%%
{line} {printf("%5d %s", lineno++, yytext);}
%%
int main()
{
yylex();
return 0;
}
int yywrap()
{
return 1;
}
结果测试:
nihao
1 nihao
this is a test lex c programming.
2 this is a test lex c programming.
YACC
能够读取用户输入的算术表达式,验证其语法是否正确,并在解析成功时输出相应的信息。
%{
#include <stdio.h>
#include <ctype.h>
#define YYSTYPE int
void yyerror(char *s);
int yylex(void);
%}
%token DIGIT
%left '+'
%left '*'
%%
line: line expr '\n' { printf("Valid syntax!"); }
| line '\n'
|
;
expr: expr '+' expr
| expr '*' expr
| '(' expr ')'
| DIGIT
;
%%
int main()
{
if (yyparse() == 0) {
printf("Parsing finished successfully.\n");
} else {
printf("Parsing failed.\n");
}
return 0;
}
int yylex(void)
{
int c = 0;
while ((c = getchar()) == ' ');
if (isdigit(c)){
ungetc(c, stdin);
scanf("%d", &yylval);
return DIGIT;
}
return c;
}
void yyerror(char *s)
{
fprintf(stderr, "%s\n", s);
}
(5+4+2)*5
Valid syntax!
8-4+2
syntax error
Parsing failed.
生成项目
点击vscode左侧图标“三角形”的CMake,然后像如下图片配置:

配置一栏选择 MSYS2中安装的GNU的GCC编译器,选择Debug模式。然后点击项目大纲中“…”的部分,选择“清理所用项目并重新配置”,然后选择“清理所用项目并重新生成”。或者点击左下角的“生成”。

结语
现在可以在build目录下看到exe可执行文件以及flex和bison目录中的c语言文件。
3245

被折叠的 条评论
为什么被折叠?



