在Windows系统中使用vscode配置CMake和win_flex_bison实现LEX和YACC

前言

最近在学校的专业课《编译原理》学习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++编译环境:

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的环境变量:

  1. 打开“设置”
  2. 找到“系统”
  3. 找到“系统信息”
  4. 找到“高级系统设置”
  5. 找到“系统属性”下的“高级“属性下的”环境变量“(在右下角)
  6. 找到”Path”
  7. 点击”编辑”,点击“新建”,粘贴路径,点击“确定”
  8. 返回上级点击“确定”
  9. 再次返回上级点击“应用”,然后“确定”

在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.hwin_bison.exewin_flex.exe文件粘贴到flex_bisontools目录下。

然后是核心文件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语言文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值