编译原理-语法分析flex&bison(一个奇怪的报错解决)

在做本次编译原理实验时出现了一个奇怪的问题
在老师给的文档里有这样一个测试案例

int main(){
	int i = 3;
	%666
	if(i - 2 == 1){  // note
		i = i + 8
	}
	float p[i = 2.52;
}

计划输出

Error type A at line 3 : Mysterious characters '%'
Error type B at line 4: Missing ';'.
Error type B at line 6: Missing ';'.
Error type B at line 7: Missing ']'.

但实际上的输出结果是
在这里插入图片描述
多出了一个missing2和一个missing1‘;’的报错
由于我给’;'编了号,可以对应查找出报错的原因,报错的missing在下面的定义位置,报错的原因是函数声明语句缺少;

//表示全局变量 结构体或函数定义
ExtDef: Specifier ExtDecList SEMI { $$ ; }
	| Specifier SEMI { $$ ; }
	| Specifier FunDec CompSt { $$; }
	| Specifier FunDec SEMI{$$;} 
	| Specifier ExtDecList error {yyError("Missing1 ';'");} //全局变量定义语句缺少';'
	| Specifier FunDec error {yyError("Missing2 ';'");} //函数声明语句缺少';'
	| Specifier error {yyError("Missing3 ';'");}  //(全局)结构体定义语句缺少';'
	;

但是在测试样例中并没有函数声明,这到底是为啥呢
经过一系列print的查找,发现在语句匹配的过程中无法进入到语句块中(在这一步放入输入语句无法输出)

//语句块{}
CompSt: LC DefList StmtList RC { $$ ; }
	;

语句块除了左右的两个’{’ '}'外由中间两部分构成,分别是变量和其他语句,如下所示

//其他语句和表达式
StmtList: Stmt StmtList { $$ ; }
	| { $$ ; }
	;
Stmt: Exp SEMI { $$ ; }
	| CompSt { $$  ;}
	| RETURN Exp SEMI { $$  ;}
	| IF LP Exp RP Stmt %prec LOWER_THAN_ELSE{ $$ ; }//表示该优先级较低
	| IF LP Exp RP Stmt ELSE Stmt { $$ ; }
	| WHILE LP Exp RP Stmt { $$ ; }
	| RETURN Exp error {yyError("Missing4 ';'");}  //return语句结尾缺少';'
	| ELSE Stmt {yyError("'else' without a previous 'if'");} //错误使用if-else语句
	| Exp error {yyError("Missing5 ';'");}  //语句结尾缺少';'
	;
//局部变量定义
DefList: Def DefList  { $$ ; }
	| { $$  ;}
	;
Def: Specifier DecList SEMI { $$ ; }
	|Specifier DecList error {yyError("Missing6 ';'");}  //局部变量定义缺少';
	; 

而在C–语法中对语句块的定义是

CompSt: LC DefList StmtList RC//左括号+变量+其他语句+右括号

再看我们的测试样例中在大括号内其实是变量定义和其他语句穿插进行,因此无法和CompSt的定义匹配上,此类在C–的语法中没有定义,会被匹配成error
因此会被匹配到Specifier FunDec error {yyError("Missing2 ';'");} //函数声明语句缺少';'
该代码块相当于匹配成了 int main() error一个函数声明缺少;

int main(){
	int i = 3;//DefList
	%666
	if(i - 2 == 1){  // StmtList
		i = i + 8
	}
	float p[i = 2.52;//DefList
}

想要解决这个问题必须去修改C–语法,让CompSt语法定义满足测试样例的需求,可以实现变量与表达式穿插放置
我们首先想到的是以下方法

CompSt: LC DefList StmtList DefList RC

会发生移进-归约冲突,且还是不能满足二者随意交替进行的情况

syntax.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]

当遇到一个代码行时有两种以上选择时就会出现该种冲突
最终的解决方法
原理:将变量和其他表达式合并成为一部分。由于DefListStmtList的结构是相同的,只有头部的StmtDef不同,尾部是一个循环体,因此将二者合并,将Stmt的定义加入Def的部分
注意:不能直接将DefList删掉,因为在Struct结构体定义中也需要用到局部变量

//语句块{}
CompSt: LC StmtList RC { $$ ; }
	;
StmtList: Stmt StmtList { $$ ; }
	| { $$ ; }
	;

Stmt: Def{ $$ ;}
	| Exp SEMI { $$ ; }
	| CompSt { $$  ;}
	| RETURN Exp SEMI { $$  ;}
	| IF LP Exp RP Stmt %prec LOWER_THAN_ELSE{ $$ ; }//表示该优先级较低
	| IF LP Exp RP Stmt ELSE Stmt { $$ ; }
	| WHILE LP Exp RP Stmt { $$ ; }
	| RETURN Exp error {yyError("Missing4 ';'");}  //return语句结尾缺少';'
	| ELSE Stmt {yyError("'else' without a previous 'if'");} //错误使用if-else语句
	| Exp error {yyError("Missing5 ';'");}  //语句结尾缺少';'
	; 
//变量定义
DefList: Def DefList  { $$ ; }
	| { $$  ;}
	;

最后的最后 他终于好了
在这里插入图片描述
nice!

一点其他的理解:
为什么最开始没有匹配上语句块也会报语句块内部的一些错比如说float p[i = 2.52;缺少右括号也可以正常输出
这是由于bison的错误匹配模式是一个栈的移进移出
在这里插入图片描述
匹配error时会先匹配到DefList,在DefList中匹配到Exp中此行的错误,当匹配到这一句时就会直接输出语句报错

	Exp:| Exp LB Exp error {yyError("Missing ']'");} //表达式中变量索引缺少']'

当匹配到代码结尾时发现不符合最初的CompSt语法定义,则不予该行匹配,匹配到了

	| Specifier FunDec error {yyError("Missing2 ';'");} //函数声明语句缺少';'

注:此代码为不完整代码且包含错误部分(dog)
发现了更改语法对语法树生成的一些影响

float f, m[6];

struct ms{
	int kk;
} ms;

int main(){
	int q[10];
	i = 3;
	ms.kk = i && fun(); 
}

int fun(int a, float f[2]){
	if(i - 2 == 1){
  	q[1] = i + ms.kk;
	}
}

上述这段代码中老师给出答案中的语法树

Program (1)
  ExtDefList (1)
    ExtDef (1)
      Specifie (1)
        TYPE : float
      ExtDecList (1)
        VarDec (1)
          ID : f
        COMMA : ,
        ExtDecList (1)
          VarDec (1)
            VarDec (1)
              ID : m
            LB : [
            INT : 6
            RB : ]
      SEMI : ;
    ExtDefList (3)
      ExtDef (3)
        Specifier (3)
          StructSpecif (3)
            STRUCT : struct
            OptTag (3)
              ID : ms
            LC : {
            DefList (4)
              Def (4)
                Specifie (4)
                  TYPE : int
                DefList (4)
                  Dec (4)
                    VarDec (4)
                      ID : kk
                SEMI : ;
              Empty : Empty
            RC : }
        ExtDecList (5)
          VarDec (5)
            ID : ms
        SEMI : ;
      ExtDefList (7)
        ExtDef (7)
          Specifie (7)
            TYPE : int
          FunDec (7)
            ID : main
            LP : (
            RP : )
          CompSt (7)
            LC : {
            DefList (8)
              Def (8)
                Specifie (8)
                  TYPE : int
                DefList (8)
                  Dec (8)
                    VarDec (8)
                      VarDec (8)
                        ID : q
                      LB : [
                      INT : 10
                      RB : ]
                SEMI : ;
              Empty : Empty
            StmtList (9)
              EStmt (9)
                Exp (9)
                  Exp (9)
                    ID : i
                  ASSIGNOP : =
                  Exp (9)
                    INT : 3
                SEMI : ;
              StmtList (10)
                EStmt (10)
                  Exp (10)
                    Exp (10)
                      Exp (10)
                        ID : ms
                      DOT : .
                      ID : kk
                    ASSIGNOP : =
                    Exp (10)
                      Exp (10)
                        ID : i
                      AND : &&
                      Exp (10)
                        ID : fun
                        LP : (
                        RP : )
                  SEMI : ;
                Empty : Empty
            RC : }
        ExtDefList (13)
          ExtDef (13)
            Specifie (13)
              TYPE : int
            FunDec (13)
              ID : fun
              LP : (
              VarList (13)
                ParamDec (13)
                  Specifie (13)
                    TYPE : int
                  VarDec (13)
                    ID : a
                COMMA : ,
                VarList (13)
                  ParamDec (13)
                    Specifie (13)
                      TYPE : float
                    VarDec (13)
                      VarDec (13)
                        ID : f
                      LB : [
                      INT : 2
                      RB : ]
              RP : )
            CompSt (13)
              LC : {
              Empty : Empty
              StmtList (14)
                Stmt (14)
                  IF : if
                  LP : (
                  Exp (14)
                    Exp (14)
                      Exp (14)
                        ID : i
                      MINUS : -
                      Exp (14)
                        INT : 2
                    RELOP : ==
                    Exp (14)
                      INT : 1
                  RP : )
                  Stmt (14)
                    CompSt (14)
                      LC : {
                      Empty : Empty
                      StmtList (15)
                        EStmt (15)
                          Exp (15)
                            Exp (15)
                              ID : q
                              ITEM (15)
                                LB : [
                                INT : 1
                                RB : ]
                            ASSIGNOP : =
                            Exp (15)
                              Exp (15)
                                ID : i
                              PLUS : +
                              Exp (15)
                                Exp (15)
                                  ID : ms
                                DOT : .
                                ID : kk
                          SEMI : ;
                        Empty : Empty
                      RC : }
                Empty : Empty
              RC : }
          Empty : Empty

而我们生成的语法树

Program (1)
  ExtDefList (1)
    ExtDef (1)
      Specifier (1)
        TYPE: float
      ExtDecList (1)
        VarDec (1)
          ID: f
        COMMA: ,
        ExtDecList (1)
          VarDec (1)
            VarDec (1)
              ID: m
            LB: [
            INT: 6
            RB: ]
      SEMI: ;
    ExtDefList (3)
      ExtDef (3)
        Specifier (3)
          StructSpecifier (3)
            STRUCT: struct
            OptTag (3)
              ID: ms
            LC: {
            DefList (4)
              Def (4)
                Specifier (4)
                  TYPE: int
                DecList (4)
                  Dec (4)
                    VarDec (4)
                      ID: kk
                SEMI: ;
              Empty: Empty
            RC: }
        ExtDecList (5)
          VarDec (5)
            ID: ms
        SEMI: ;
      ExtDefList (7)
        ExtDef (7)
          Specifier (7)
            TYPE: int
          FunDec (7)
            ID: main
            LP: (
            RP: )
          CompSt (7)
            LC: {
            StmtList (8)
              Def (8)
                Specifier (8)
                  TYPE: int
                DecList (8)
                  Dec (8)
                    VarDec (8)
                      VarDec (8)
                        ID: q
                      LB: [
                      INT: 10
                      RB: ]
                SEMI: ;
              StmtList (9)
                Stmt (9)
                  Exp (9)
                    Exp (9)
                      ID: i
                    ASSIGNOP: =
                    Exp (9)
                      INT: 3
                  SEMI: ;
                StmtList (10)
                  Stmt (10)
                    Exp (10)
                      Exp (10)
                        Exp (10)
                          ID: ms
                        DOT: .
                        ID: kk
                      ASSIGNOP: =
                      Exp (10)
                        Exp (10)
                          ID: i
                        AND: &&
                        Exp (10)
                          ID: fun
                          LP: (
                          RP: )
                    SEMI: ;
                  Empty: Empty
            RC: }
        ExtDefList (13)
          ExtDef (13)
            Specifier (13)
              TYPE: int
            FunDec (13)
              ID: fun
              LP: (
              VarList (13)
                ParamDec (13)
                  Specifier (13)
                    TYPE: int
                  VarDec (13)
                    ID: a
                COMMA: ,
                VarList (13)
                  ParamDec (13)
                    Specifier (13)
                      TYPE: float
                    VarDec (13)
                      VarDec (13)
                        ID: f
                      LB: [
                      INT: 2
                      RB: ]
              RP: )
            CompSt (13)
              LC: {
              StmtList (14)
                Stmt (14)
                  IF: if
                  LP: (
                  Exp (14)
                    Exp (14)
                      Exp (14)
                        ID: i
                      MINUS: -
                      Exp (14)
                        INT: 2
                    RELOP: ==
                    Exp (14)
                      INT: 1
                  RP: )
                  Stmt (14)
                    CompSt (14)
                      LC: {
                      StmtList (15)
                        Stmt (15)
                          Exp (15)
                            Exp (15)
                              Exp (15)
                                ID: q
                              LB: [
                              Exp (15)
                                INT: 1
                              RB: ]
                            ASSIGNOP: =
                            Exp (15)
                              Exp (15)
                                ID: i
                              PLUS: +
                              Exp (15)
                                Exp (15)
                                  ID: ms
                                DOT: .
                                ID: kk
                          SEMI: ;
                        Empty: Empty
                      RC: }
                Empty: Empty
              RC: }
          Empty: Empty

empty的个数是匹配不上的
以CompSt(13)处的语法树为例

  			CompSt (13)
              LC : {
              Empty : Empty
              StmtList (14)
                Stmt (14)
                  IF : if
                  LP : (
int fun(int a, float f[2]){
	if(i - 2 == 1){
  	q[1] = i + ms.kk;
	}

由于语句块中没有DefList的部分,因此在原有的C–语法中会把第一部分输出为空,而我们的C–语法将DefList和StmtList合并后,会将第一个if语句直接匹配到StmtList 因此会少一个Empty 语法树的内部结构也会有一些差异

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机科学中的一门重要课程,涉及了很多与编译器设计和实现相关的概念和技术。而C-minus语法分析则是编译原理中的一个重要部分,它使用了flexbison这两个工具来实现。接下来我将详细介绍C-minus语法分析的相关内容。 C-minus是一种简化版的C语言,它具有类似于C语言的语法和语义。语法分析是编译器的第二个阶段,主要负责通过解析输入的源代码来构建抽象语法树。在C-minus语法分析中,我们使用flexbison这两个工具来实现词法分析和语法分析flex一个用于生成词法分析器的工具,它通过定义一系列正则表达式规则来识别源代码中的各种词法单元,如关键字、标识符、常量等。在C-minus语法分析中,我们可以使用flex来识别源代码中的词法单元,并将它们传递给bison进行后续的语法分析bison一个用于生成语法分析器的工具,它通过定义一系列文法规则来分析词法单元之间的语法关系,同时生成一个由这些规则构成的抽象语法树。在C-minus语法分析中,我们可以使用bison来定义C-minus语言的文法规则,并将其与词法单元进行匹配,从而生成抽象语法树。 在C-minus语法分析中,我们需要定义C-minus语言的文法规则,如声明语句、函数定义、循环语句等。通过使用flexbison这两个工具,我们可以将这些规则转化为相应的词法和语法规则,并实现一个完整的C-minus语法分析器。 总而言之,C-minus语法分析编译原理中的一个重要环节,通过使用flexbison这两个工具,我们可以实现一个功能完善的C-minus语法分析器,从而为后续的语义分析和代码生成打下基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值