Compiler construction Flex和Bison给出了分段错误(堆芯转储)
我正在尝试使用flex和bison为一种叫做“FUNC”的简单语言创建一个编译器。但它给了我一个分段错误,在花了几个小时之后,我仍然无法修复它。如果你们能帮忙,我会非常感激的。谢谢 Flex文件“func.lex”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;} “读取”{返回读取
%{
#包括“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