Compiler construction Flex和Bison给出了分段错误(堆芯转储)

Compiler construction Flex和Bison给出了分段错误(堆芯转储),compiler-construction,segmentation-fault,bison,flex-lexer,Compiler Construction,Segmentation Fault,Bison,Flex Lexer,我正在尝试使用flex和bison为一种叫做“FUNC”的简单语言创建一个编译器。但它给了我一个分段错误,在花了几个小时之后,我仍然无法修复它。如果你们能帮忙,我会非常感激的。谢谢 Flex文件“func.lex” %{ #包括“tokens.h” //#包括“y.tab.h” %} 数字[0-9] 识别号[a-zA-Z][a-zA-z0-9]* %% 函数{返回函数;} “返回”{return returns;} “开始”{返回开始;} “end”{return end;} “读取”{返回读取

我正在尝试使用flex和bison为一种叫做“FUNC”的简单语言创建一个编译器。但它给了我一个分段错误,在花了几个小时之后,我仍然无法修复它。如果你们能帮忙,我会非常感激的。谢谢

Flex文件“func.lex”

%{
#包括“tokens.h”
//#包括“y.tab.h”
%}
数字[0-9]
识别号[a-zA-Z][a-zA-z0-9]*
%%
函数{返回函数;}
“返回”{return returns;}
“开始”{返回开始;}
“end”{return end;}
“读取”{返回读取;}
“写入”{返回写入;}
“if”{返回if;}
“然后”{返回然后;}
“else”{return else;}
“变量”{返回变量;}
“while”{返回while;}
“循环”{返回循环;}
“Less”{返回Less;}
“LessEq”{return LessEq;}
“Eq”{返回Eq;}
“NEq”{返回NEq;}
“({return LB;}
“{return RB;}”
“Plus”{return Plus;}
“时间”{返回时间;}
“减号”{返回减号;}
“Divide”{返回Divide;}
“,”{返回逗号;}
“:=”{return ASSIGN;}
“;”{返回半;}
{DIGIT}+{返回号码;}
{IDENT}{返回名称;}
{返回EOF;}
[\t\n]+/*吃光空白*/
%%
int yywrap(){return EOF;}
Yacc文件“func.y”

%{
//#包括“tokens.h”
#包括
#包括
外部文件*yyin;
外部字符*文本;
外部内部yylex(无效);
extern int yyparse();
无效错误(常量字符*s);
int yylex(无效);
int-symb;
%}
/*****************野牛宣言**********************/
%union//定义所有可能的语义数据类型(字符串和数字)
{
整数;
字符*名称;
_Bool COND;//返回条件表达式的值。其中一个$$的值可以是0或1
}
%启动程序
%型号
%类型名
%令牌函数返回变量开始结束逗号半赋值
读写
否则
WHILE循环
LB-RB
减去LESSEQ NEQ
加减乘除
名称编号//与下面“操作”中使用的大小写相同(与FUNC语法相同)
%%
//语法规则
节目:funcs
;                // ::= 
func:func“;”/:=;[]
|func”;“func”
;
func:FUNCTION NAME“(“”)BEGIN命令END FUNCTION/*::=函数([])[返回][变量]BEGIN-END函数*/
|函数名“(“args”)”开始命令结束函数
|函数名(“args”)返回名称BEGIN命令END函数
|函数名“(“”)返回名称BEGIN命令END函数
|函数名“(“”)开始命令变量args结束函数
|函数名“(“args”)”开始命令变量args结束函数
|函数名“(“”)返回NAME BEGIN命令变量args END函数
|函数名“(“args”)”返回名称BEGIN命令变量args END函数
;
args:NAME/:=[,]
|名称“,”args
;
命令:命令“;”/:=;[]
|命令“;”命令
;
命令:分配//:=| | | |读|写
|如果
|当
|阅读
|写
;
assign:NAME::=“expr{$$=$1=$3;}/:==”
//assign:NAME assign expr{$1=$3;}
;
if:if condexpr-THEN命令END if/::=if-THEN[else]END if
|如果condexpr然后命令ELSE命令结束如果
;
while:whilecondexpr循环命令结束循环
;          // ::= while循环结束循环
读:读数字
|读名字
;
write:write expr
;
condexpr:bop(“expr”、“expr”)”
;                     // ::=  (  )
国际收支平衡表:减/:=减| LessEq | Eq | NEq
|莱塞克
|情商
|NEQ
;

Less:Less“(“NUMBER”,“NUMBER”)”{如果($3你的词汇定义有各种错误;由于缺乏关于问题的详细信息,我不知道这些错误在多大程度上导致了你的问题,所以我只列出它们:

  • 使用bison头文件;不要替换自己的头文件。 bison生成的头文件包含
    YYSTYPE
    的定义,解析器和扫描程序必须对此定义达成一致。它还包含各种令牌的正确定义,这在两个文件中也必须相同。您不显示
    token.h
    的内容,但其使用不提供任何信心;如果您这样做是为了掩盖其他问题,请在继续之前解决其他问题

  • 不要替代非标准EOF处理 (除非您需要这些功能之一,并且您应该知道需要哪些功能。)
    noyywrap
    选项从生成的lexer中删除调用
    yywrap
    的代码,以便lexer在遇到输入流中的EOF时立即返回输入结束指示。
    noinput
    nounput
    删除
    input()和
    unput()的定义
    函数,如果您的lexer操作未使用这些函数,则会导致编译器警告。(顺便说一句,您确实是在启用编译器警告的情况下编译的,对吗?不启用编译器警告是一个很好的方法,可以忽略您正在自食其果的事实。)

    nodefault
    选项将删除(f)lex为无法识别的输入字符生成的默认规则,并在某些输入字符可能无法识别时发出警告。(这不会影响默认的
    操作。对于未识别的输入,默认的flex操作是
    ECHO
    ,这意味着未识别的字符将被简单地发送到标准输出,而不会生成任何类型的错误消息。这(几乎)不是您想要的,也可以用来掩盖真正的错误

    如果使用
    yywrap
    ,则表示输入结束的常规返回值为
    1
    (“true”),而不是
    EOF
    ,尽管
    EOF
    可以工作

  • 如果解析器需要语义值,则需要
        %{
    #include "tokens.h"
    //#include "y.tab.h"
    %}
    
    DIGIT    [0-9]
    IDENT   [a-zA-Z][A-Za-z0-9]*
    
    %%
    
    "function"  {return FUNCTION;}
    "returns"   {return RETURNS;}
    "begin" {return BEGIN;}
    "end"  {return END;}
    "read"  {return READ;}
    "write" {return WRITE;}
    "if"    {return IF;}
    "then"  {return THEN;}
    "else"  {return ELSE;}
    "variables" {return VARIABLES;}
    "while" {return WHILE;}
    "loop"  {return LOOP;}
    "Less"  {return LESS;}
    "LessEq"    {return LESSEQ;}
    "Eq"    {return EQ;}
    "NEq"   {return NEQ;}
    "("     {return LB;}
    ")"     {return RB;}
    "Plus"  {return PLUS;}
    "Times"  {return TIMES;}
    "Minus"  {return MINUS;}
    "Divide"  {return DIVIDE;} 
    "," {return COMMA;}
    ":="    {return ASSIGN;}
    ";"  {return SEMI;}
    
    {DIGIT}+ {return NUMBER;}
    {IDENT}  {return NAME;}
    <<EOF>> {return EOF;}
    
    [ \t\n]+          /* eat up whitespace */
    
    
    %%
    
    int yywrap() { return EOF; }
    
    %{
    //#include "tokens.h"
    #include <stdio.h>
    #include <stdlib.h>
    extern FILE * yyin;
    extern char * yytext;
    extern  int yylex(void);
    extern  int yyparse();
    void yyerror( const char *s);
    int yylex(void);
    int symb;
    %}
    
    /*****************bison declarations**********************/
    
    %union               //defining all possible semantic data types (strings and digits)
    {
      int       NUMBER; 
      char *    NAME;
      _Bool         COND;   //return value of conditional expressions. one of our $$ can have value 0 or 1
    }
    
    %start program
    
    %type <NUMBER> NUMBER
    %type <NAME> NAME
    
    %token FUNCTION RETURNS VARIABLES BEGIN END COMMA SEMI ASSIGN
    READ WRITE 
    IF THEN ELSE
    WHILE LOOP
    LB RB
    LESS LESSEQ EQ NEQ 
    PLUS MINUS TIMES DIVIDE
    NAME NUMBER      //same case as that used in "operations" below (same as FUNC syntax)
    
    %%
    //grammar rules
    
    program: funcs
        ;                //<program> ::= <funcs>
    
    funcs: func ";"                       //<funcs> ::= <func>; [<funcs>]
              |func ";" funcs
        ;
    
    func: FUNCTION NAME "("")" BEGIN commands END FUNCTION           /*<func> ::= function <name>([<args>])[returns <name>] [variables <args>] begin <commands> end function*/
          |FUNCTION NAME "(" args ")" BEGIN commands END FUNCTION
          |FUNCTION NAME "(" args ")" RETURNS NAME BEGIN commands END FUNCTION
          |FUNCTION NAME "("")" RETURNS NAME BEGIN commands END FUNCTION
          |FUNCTION NAME "("")" BEGIN commands VARIABLES args END FUNCTION
          |FUNCTION NAME "(" args ")" BEGIN commands VARIABLES args END FUNCTION
          |FUNCTION NAME "("")" RETURNS NAME BEGIN commands VARIABLES args END FUNCTION
          |FUNCTION NAME "(" args ")" RETURNS NAME BEGIN commands VARIABLES args END FUNCTION
        ;
    
    args: NAME                   //<args> ::= <name> [,<args>]
        |NAME "," args 
        ;
    
    commands: command ";"           //<commands> ::= <command>; [<commands>]
              |command ";" commands
        ;
    
    command: assign                            //<command> ::= <assign> | <if> | <while> | read <name> | write <expr>
             |if
             |while
             |read
             |write 
        ;
    
    assign: NAME ":=" expr  {$<NAME>$=$1=$<NUMBER>3;}     //<assign> ::= <name> := <expr>
    //assign: NAME ASSIGN expr  {$1=$3;}
        ;
    
    if: IF condexpr THEN commands END IF                 //<if> ::= if <condexpr> then <commands> [else <commands>] end if
        |IF condexpr THEN commands ELSE commands END IF
        ;
    
    while: WHILE condexpr LOOP commands END LOOP
        ;          //<for> ::= while <condexpr> loop <commands> end loop
    
    read: READ NUMBER
    |READ NAME 
        ;
    
    write: WRITE expr
        ;
    
    condexpr: bop "(" expr "," expr ")"
        ;                     //<condexpr> ::= <bop> ( <exprs> )
    
    bop: LESS                    //<bop> ::= Less | LessEq | Eq | NEq
           |LESSEQ
           |EQ
           |NEQ
        ;
    
    
    Less: LESS "(" NUMBER "," NUMBER ")"           {if($<NUMBER>3<$<NUMBER>5)$<COND>$=1;} ;
    
    LessEq: LESSEQ "(" NUMBER "," NUMBER ")"     {if($<NUMBER>3<=$<NUMBER>5)$<COND>$=1;} ;
    
    Eq: EQ "(" NUMBER "," NUMBER ")"             {if($<NUMBER>3=$<NUMBER>5)$<COND>$=1;} ;
    
    NEq: NEQ "(" NUMBER "," NUMBER ")"          {if($<NUMBER>3!=$<NUMBER>5)$<COND>$=1;} ;
    
    
    
    
    exprs: expr                   //<expr> [,<exprs>]
               |expr "," exprs 
        ;
    
    
    expr: NAME
         |NUMBER
             |NAME "(" exprs ")"               //<name>[( <exprs> )]   |   <number> 
        ;
    
    /***************idk if we need this. dunno which file to describe these operations in ***********************/
    
    Plus: PLUS "(" NUMBER "," NUMBER ")"       {$<NUMBER>$=$3+$5; } ;        //S1=plus  $2=(  $3=expr  $4=   $5=expr   $6=)
    Minus: MINUS "(" NUMBER "," NUMBER ")"   {$<NUMBER>$=$3-$5; } ;
    Times: TIMES "(" NUMBER "," NUMBER ")"   {$<NUMBER>$=$3*$5; } ;
    Divide: DIVIDE "(" NUMBER "," NUMBER ")" {$<NUMBER>$=$3/$5; } ;
    
    %%
    
    //c code
    
    /*
    int main(int c, char * * argv) {
    
            if ((yyin = fopen(argv[1], "r")) == NULL) {
    
                    printf("can't open %s\n", argv[1]);
    
                    exit(0);
    
            }
            symb = yylex();
            yyparse();
           // program(1);
    
            fclose(yyin);
    
    }
    */
    int main (char * * argv)
    {
      if ((yyin = fopen(argv[1], "r")) == NULL) {
    
                    printf("can't open %s\n", argv[1]);
    
                    exit(0);
    }
     yylex();
    }
    
    void yyerror(const char *s)
    {
      extern int yylineno;  // defined and maintained in lex.c
      extern char *yytext;  // defined and maintained in lex.c
    
      /*std::cerr << "ERROR: " << s << " at symbol \"" << yytext;
      std::cerr << "\" on line " << yylineno << std::endl;
      exit(1);*/
    printf("parse error  Message: ", s);
    fflush(1);
    exit(-1);
    }
    
    /*int yyerror(char *s)
    {
      return yyerror(string(s));
    }*/
    
    %{
    #include "tokens.h"
    //#include "y.tab.h"
    %}
    
    <<EOF>> {return EOF;}
    
    %option noyywrap noinput nounput nodefault
    
    %token <str> NAME
    %type  <number> expr