vscode环境下的flex&bison


title: vscode环境下的flex&bison
top: 42
date: 2024-02-28 17:23:01
tags:

  • vscode
  • flex
  • bison
    -windows

categories:

  • C++

flex&bison安装

linux系统

  • 一般都会带flex和bison命令的

windows系统

  • 下载软件

  • 解压压缩包到指定位置后,配置系统环境

    • 新建两个变量和值
    变量
    bison_hairy$(安装路径)\UnxUtils\usr\local\share\bison.hairy
    bison_simple$(安装路径)\UnxUtils\usr\local\share\bison.simple
    • Path环境变量
    • $(安装路径)\UnxUtils\usr\lib
    • $(安装路径)\UnxUtils\usr\wbin

vscode环境配置(MSVC+cmake)

工程目录结构

demo
├── .vscode
│    ├── c_cpp_properties.json
│    ├── launch.json
│    ├── setting.json
│    └── tasks.json
├── flex_bison
│    ├── bison.y
│    └── flex.l
└── CMakeLists.txt

文件

  • CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(demo)
set(CMAKE_CXX_COMPILER cl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_GENERATOR_PLATFORM x64)

add_executable(demo lex.yy.c y.tab.c)
  • c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                "D:/install/major/vs2019/VC/Tools/MSVC/14.29.30133/include",
                "D:/Windows Kits/10/Include/10.0.19041.0/ucrt"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "windowsSdkVersion": "10.0.19041.0",
            "compilerPath": "cl.exe",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "windows-msvc-x64",
            "configurationProvider": "ms-vscode.cmake-tools"
        }
    ],
    "version": 4
}
  • launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(Windows) Launch",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/cmake-build/Debug/demo.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "console": "integratedTerminal",
            "preLaunchTask": "cbuild"
        }

    ]
}
  • tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "options": {
        "cwd": "${workspaceFolder}"
    },
    "tasks": [
        {
            "label": "cbuild",
            "type": "shell",
            "command": "cmake",
            "args": [
                "--build", "${workspaceFolder}/cmake-build",
                "--target", "${workspaceFolderBasename}",
                "-j", "4"
            ],
            "dependsOn":[
                "build"
            ]
        },
        {
            "label": "build",
            "type": "shell",
            "command": "cmake",
            "args": [
                "-DCMAKE_BUILD_TYPE=Debug",
                "-S", "${workspaceFolder}",
                "-B", "${workspaceFolder}/cmake-build"
            ],
            "dependsOn":[
                "flex",
                "bison"
            ]
        },
        {
            "label": "flex",
            "type": "shell",
            "command": "flex ${workspaceFolder}/flex_bison/flex.l",
        },
        {
            "label": "bison",
            "type": "shell",
            "command": "bison --yacc -dv ${workspaceFolder}/flex_bison/bison.y",
        }
    ]
}
  • flex.l
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
void yyerror(char *);
%}
NUM [1-9]+[0-9]*|0
%%
{NUM}		                printf("NUM:%s ", yytext);sscanf(yytext,"%d",&yylval.calc);;return NUM;
"+"							return ADD;
"-"							return SUB;
"*"							return MUL;
"/"							return DIV;
"^"                         return SQU;
"%"                         return REM;
[a-zA-Z_$]+[a-zA-Z_$0-9]*	return VAR;
\n                          return CR;
[ \t]+                     /* ignore whitespace */;
.

%%

  • bison.y
%{
#include <stdio.h>
#include <string.h>
#include <math.h>

int yylex(void);
void yyerror(char *);
%}
%union {
    int calc;
}

%token ADD SUB MUL DIV CR SQU REM VAR
%token <calc> NUM
%type <calc> expression term square
%%
   line_list: line
            | line_list line
            ;
    line : expression CR  {printf(">>%d\n",$1);}

    expression: term {printf("expr term\n")}
            | expression ADD term   {$$=$1+$3;}
            | expression SUB term   {$$=$1-$3;}
            ;

    term: square   {printf("y:NUM:%d\n", $1);}
            | term MUL square  {printf("*\n");$$=$1*$3;}
            | term DIV square  {$$=$1/$3;}
            | term REM square  {$$=$1%$3;}
            ;
   square: NUM
            | square SQU NUM  {$$=pow($1,$3);}
            ;

%%
void yyerror(char *str){
    fprintf(stderr,"error:%s\n",str);
}

int yywrap(){
    return 1;
}
int main()
{
    yyparse();
}

运行结果

2*2*2-21*2^5 # 此为命令行输入
NUM:2 y:NUM:2
NUM:2 *
NUM:2 *
expr term
NUM:21 y:NUM:21
NUM:2 NUM:5 *
>>-664	# 此为解析后输出值

flex&bison

flex

  • 命令

flex flex.l (flex.l为flex编码文件)

  • 输出

输出文件名为lex.yy.c

flex结构规范

flex程序由三部分构成:定义部分、规则部分和用户子例程。这三个部分通过由两个百分号组成的行来分隔。前两个部分是必需的,但他们的内容可以为空。第三部分和前面的**%%**是可以省略。

...定义部分...
%%
...规则部分...
%%
...用户子例程...
定义部分

​ 定义部分包括选项、文字块、定义、开始条件和转换。其中,以空白字符开始的行将被原样拷贝到C文件中。

规则部分

​ 规则部分包括模式行和C代码。以空白字符开始或处于%{和%}之间的内容被认为是C代码,它们会被原样地拷贝到yylex()中。在规则部分开头出现的C代码也会出现在yylex()开头,它可以包含词法分析器中需要使用的变量声明,以及每次调用yylex()所需运行的代码。

​ 以其他任何字符开始的行就是i模式行。模式行包含一个模式、一些空白字符以及输入被该模式匹配时所执行的C代码。如果C代码超过一条语句或跨越多行,它必须用括号括起,即符号**{ }%{ %}**。

当flex词法分析器运行时,它根据规则部分的模式进行匹配。每次它发现一个匹配,它执行这个模式所关联的C代码。

如果模式后紧跟一个 | 而不是C代码的话,该模式使用与这个文件中下一模式相同的C代码。当输入字符无法匹配任何模式时,词法分析器将被认为它匹配了一个动作代码为ECHO的模式,相应地,该记号的拷贝被输出。

用户子例程

​ 用户子例程的内容将被原样拷贝到C文件,通常包括规则中需要调用的例程。如果重定义了yywrap(),该例程的新版本或相关支撑例程会出现在这里。



flex内置功能函数

%option
option选项释义
%option nounput禁用 yyunput 函数,在扫描时就不将字符重新放回输入缓冲区
%option noyywrap禁用再输入结束时的自动调用yywrap
%option case-insensitive开启大小写不敏感模式,即忽略大小写匹配
%option noyylineno禁用行号追踪
%option debug开启调试模式,生成更多的调试相关信息
yylineno(行号)

​ 可以利用%option yylineno,flex会定义yylineno来包含当前行号,并且它会在每次遇到\n字符时自动地更新行号。

​ 词法分析器本身并不初始化yylineno,所以需要在每次开始读取文件时把它设置为1。

yyrestart()

​ 可以调用yyrestart(f)来使得词法分析器从打开的标准输入输出文件f来读取输入。

yywrap()

​ 当词法分析器到达文件末尾时,它可以选择性地调用例程yywrap()来了解下一步操作。如果yywrap()返回0,词法分析器将继续分析;如果它返回1,词法分析器将返回一个零记号来表明文件结束。如果词法分析器不使用yywrap()来切换文件,可用选项%option noyywrap来移除对yywrap()`的调用。

bison

  • 命令

bison --yacc -dv bison.y (bison.y 为bison编码文件)

  • 输出

输出文件 y.output y.tab.c y.tab.h

bison结构规范

fbison程序由三部分构成:定义部分、规则部分和用户子例程。这三个部分通过由两个百分号组成的行来分隔。前两个部分是必需的,但他们的内容可以为空。第三部分和前面的**%%**是可以省略。

...定义部分...
%%
...规则部分...
%%
...用户子例程...
符号

bison语法由符号组成,它们是语法的“单词”。符号由一连串字母、数字、点号和下划线组成,但首字母不能是数字。

符号error代表错误恢复;其他符号bison没有预先的设定。

由词法分析器产生的符号被称为终结符(terminal symbol)或记号(token)。

在规则左部定义的符号被称为非终结符(nonterminal symbol)。

记号也可以是直接用引号引起的文字字符。

定义部分

定义部分可以包含文字块,他们是被原样拷贝到生成的C文件的开始部分的C代码,文字块存在于%{和%}或者%code中,通常包括声明#include行。

声明包括%union、%start、%token、%type、%left、%right和%nonassoc。

%code块

语句格式为:

%code [place] {
	... C代码 ...
}

其中,选项place为限定符,表明C代码在生成程序中的放置位置。位置值包括top/provides/requires,对应的位置为顶部/YYSTYPE定义前/YYSTYPE定义后

规则部分

规则部分包含语法规则和语义动作的C代码。

动作

动作(action)是bison匹配语法中一条规则时执行的C代码。

动作必须是C语言的符合语句。动作可以通过一个美元符号加上一个数字来使用规则中语法符号所关联的值,冒号后第一个语法符号的数字是1,如:

date: month '/' day '/' year	{printf("date %d-%d-%d", $1, $3, $5);}

KaTeX parse error: Expected '}', got 'EOF' at end of input: …则,bison默认动作: `{=$1;}`

如果规则没有右部符号,而左部符号又声明了类型,则必须为它编写一个语义动作来赋值。

嵌入动作

bison可以支持嵌入在规则中间的语义动作。

thing: A {printf("seen an A");} B;
// <------------------------------------>
thing: A fakename B;
fakename: {printf("seen an A");}

//以上两个部分是等价的
用户子例程部分

用户子例程的内容将被bison原样拷贝到C文件。这个部分通常包括语义动作中需要调用的例程。

错误记号和错误恢复

bison语法分析器会尽可能造地检测语法错误,即一旦发现一个记号没有合适的分析时,就会报错。当bison检测到无法分析的输入时,它将尝试基于以下步骤来进行错误恢复:

  1. 调用yyerror(“syntax error”)。这通常报告错误给用户。
  2. 抛弃任何部分分析的规则,知道回到一个能够移进特殊符号error的状态。
  3. 重新开始分析,首先会移进一个error。
  4. 如果在成功移进三个符号之前另一错误发生,bison不会报告该错误,直接回到步骤2。

参考链接

[1] 手把手教你win10下lex与yacc的安装_lex windows安装教程-CSDN博客

[2] flex与bison中文版 第二版

[3] 手把手教程-lex与yacc/flex与bison入门(一)(使用windows环境)-CSDN博客

[]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值