编译系统实验一 Part 2 语法分析和错误恢复

实验任务

  • 使用bison实现c--语法分析器

    1. 完成语法分析,生成语法分析树
    2. 识别语法错误,输出错误信息,完成错误恢复
    3. 识别单行和多行注释,不支持嵌套注释(识别为语法错误)
  • 实现效果源码

    // 例1.2
    int main()
    {
         
        float a[10][2];
        int i;
        a[5,3] = 1.5;
        if(a[1][2] == 0) i = 1 else i = 0;
        a(x);
    }
    

    在这里插入图片描述

    // 例1.3
    int inc()
    {
         
        int i;
        i = i + 1;
    }
    

    在这里插入图片描述

    // 例1.4
    struct Complex
    {
         
        float real, image;
    };
    int main()
    {
         
        struct Complex x;
        y.image = 3.5;
    }
    

    在这里插入图片描述

    // 例1.5
    int main()
    {
         
        int i = 0123;
        int j = 0x3F;
    }
    

    在这里插入图片描述

    // 例1.6
    int main()
    {
         
        int i = 09;
        int j = 0x3G;
    }
    

    在这里插入图片描述

    // 例1.7
    int main()
    {
         
        float i = 1.05e-4;
    }
    

    在这里插入图片描述

    // 例1.8
    int main()
    {
         
        float i = 1.05e;
    }
    

    在这里插入图片描述

    // 例1.9
    int main()
    {
         
        // line comment
        /*
        block comment
        */
        int i = 1;
    }
    

    在这里插入图片描述

    // 例1.10
    int main()
    {
         
        /*
        comment
        /*
        nested comment
        */
        */
        int i = 1;
    }
    

    在这里插入图片描述

实验步骤一、熟悉bison文件结构,和flex的联合

  • 实验指导书1.2.7-1.2.15
  • 参考

实验步骤二、熟悉bison文件编写

  1. 首部包含lex.l生成的词法分析程序lex.yy.c

    %{
         
    	#include "lex.yy.c"   
    %}
    
  2. syntax.y词法单元(非终结符)声明

    %token INT
    %token FLOAT
    %token SEMI
    %token COMMA
    %token ASSIGNOP
    %token RELOP
    %token PLUS
    %token MINUS
    %token STAR
    %token DIV
    %token AND
    %token OR
    %token DOT
    %token NOT
    %token TYPE
    %token LP
    %token RP
    %token LB
    %token RB "]"
    %token LC
    %token RC
    %token STRUCT
    %token RETURN
    %token IF
    %token ELSE
    %token WHILE
    %token ID
    
  3. syntax.y产生式规则(此处无生成语法树相关内容)

    /* 全局变量及函数定义 */
    Program : 
        ExtdefList {
         
            printf("规约为正确的程序\n");
        }
        ;
    ExtdefList : 
        Extdef ExtdefList {
         
            printf("规约为定义全局变量或函数\n");
        }
        | /* empty */ {
         
            printf("所有全局变量及函数定义完毕\n");
        }
        ;
    Extdef : 
        Specifier ExtDecList SEMI {
          /* 声明变量列表 */ /* 结构体全局变量 */
            printf("规约为定义全局变量\n");
        } 
        | Specifier SEMI /* 声明结构体 */ {
         
            printf("规约为定义结构体\n");
        }
        | Specifier FunDec CompSt /* 声明函数 */ {
         
            printf("规约为定义函数\n");
        }
        ;
    ExtDecList : 
        VarDec {
         
            printf("规约为定义最后一个全局变量\n");
        }
        | VarDec COMMA ExtDecList {
         
            printf("规约为继续定义全局变量\n");
        }
        ;
    
    /* 变量类型 */
    Specifier : 
        TYPE {
          /* 基本类型 */
            printf("规约为基本类型\n");
        }
        | StructSpecifier /* 结构体 */ {
         
            printf("规约为结构体类型\n");
        }
        ;
    StructSpecifier : 
        STRUCT OptTag LC DefList RC /* 定义结构体 */ {
         
            printf("规约为结构体定义语句\n");
        }
        | STRUCT Tag /* 声明结构体变量 */ {
         
            printf("规约为结构体声明语句\n");
        }
        ;
    OptTag : 
        ID {
         
            printf("规约为结构体名(定义语句中)\n");
        }
        | /* empty */ {
         
            printf("规约为空结构体\n");
        }
        ;
    Tag : ID {
         
            printf("规约为结构体名(声明语句中)\n");
        }
        ;
    
    /* 变量函数定义 */
    VarDec : 
        ID {
          /* 变量名 */
        }
        | VarDec LB INT RB {
          /* 数组 */
            printf("规约为数组\n");
        }
        ;
    FunDec : 
        ID LP VarList RP {
          /* 有参函数 */
            printf("规约为定义有参函数\n");
        }
        | ID LP RP {
          /* 无参函数 */
            printf("规约为无参函数\n");
        }
        ;
    VarList : 
        ParamDec COMMA VarList {
          /* 参数列表 */
            printf("规约为定义函数参数列表\n");
        }
        | ParamDec {
         
            printf("规约为最后一个函数参数\n");
        }
        ;
    ParamDec : 
        Specifier VarDec {
          /* 单个参数 */
            printf("规约为定义函数参数\n");
        }
        ;
    
    /* 函数体 */
    CompSt : 
        LC DefList StmtList RC {
         
            printf("规约为定义函数体/语句块\n");
        }
        ;
    StmtList : 
        Stmt StmtList {
         
            printf("规约为定义多个语句块\n");
        }
        | /* empty */ {
         
            printf("规约为语句块定义结束\n");
        }
        ;
    Stmt : 
        Exp SEMI {
         
            printf("规约为定义表达式\n");
        }
        | CompSt {
         
            printf("规约为定义内部函数体/语句块\n");
        }
        | RETURN Exp SEMI {
         
            printf("规约为定义返回语句\n");
        }
        | IF LP Exp RP Stmt %prec LOWER_THAN_ELSE {
          /* 加优先级 */
            printf("规约为定义if语句\n");
        }
        | IF LP Exp RP Stmt ELSE Stmt {
         
            printf("规约为定义if-else语句\n");
        }
        | WHILE LP Exp RP Stmt {
         
            printf("规约为定义while语句\n");
        }
        ;
    /* 局部变量 */
    DefList : 
        Def DefList {
         
            printf("规约为定义多个类型的局部变量\n");
        }
        | /* empty */ {
         
            printf("规约为定义局部变量结束\n");
        
  • 15
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值