我正在尝试使用flex和bison来创建一个名为" FUNC"的简单语言的编译器。但它给了我一个分段错误,花了几个小时后,我仍然无法解决它。如果你们能提供帮助,我们真的很感激。谢谢!
Flex FIle" func.lex"
%{
#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; }
Yacc文件&#34; func.y&#34;
%{
//#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));
}*/
答案 0 :(得分:1)
你的词汇定义有各种错误;由于缺乏有关问题的详细信息,我不知道他们中任何一个人在多大程度上对您的问题做出了贡献,所以我只会列出它们:
%{
#include "tokens.h"
//#include "y.tab.h"
%}
bison生成的头文件包含YYSTYPE
的定义,解析器和扫描器必须同意此定义。它还包含各种标记的正确定义,在两个文件中也必须相同。你没有显示token.h
的内容,但它的使用没有任何信心;如果你这样做是为了掩盖其他一些问题,修复另一个问题,然后继续。
<<EOF>> {return EOF;}
词法分析器和扫描器之间的协议是词法分析器将返回令牌ID 0以表示输入结束。 EOF
的值通常为-1,这不是有效的标记号(标记号是非负整数,并且生成的解析器将无法正确处理。默认情况下, (f)lex插入一个适当的默认文件结束规则,它做了正确的事情,你应该依赖这种行为。
一个好习惯是将以下定义放在(f)lex定义的序言中:
%option noyywrap noinput nounput nodefault
(除非您需要其中一个功能,并且您应该知道需要哪些功能。)noyywrap
选项会从生成的词法分析器中删除调用yywrap
的代码,以便词法分析器立即返回当它从输入流遇到EOF时输入指示的结束。 noinput
和nounput
删除了input()
和unput()
函数的定义,如果您的词法分析器操作未使用它们,则会导致编译器警告。 (顺便说一句,你编译时启用了编译器警告,对吧?不启用编译器警告是一种很好的方法,可以忽略你自己在脚下射击的事实。)
nodefault
选项为无法识别的输入字符删除(f)lex生成的默认规则,并警告您是否可能无法识别某些输入字符。 (这不会影响默认的<<EOF>>
操作。无法识别的输入上的默认flex操作是ECHO
,这意味着无法识别的字符将被简单地发送到标准输出而不会生成任何类型的错误消息。 (几乎)从来不是你想要的,也可以用来掩盖真正的错误。
如果您使用yywrap
,则表示输入结束的常规返回值为1
(&#34; true&#34;),而不是EOF
,尽管{{1}将会有效。
在您的解析器中,您声称EOF
令牌的语义值类型为NAME
。 (重复使用令牌名称作为标记名非常不明智;您应该修复它。)但是,返回NAME
令牌的flex操作不会填充语义值。最可能的结果是解析器在期望有效NAME
时会收到NULL
,这肯定会导致段错误。
您的解析器定义也存在一些问题,应予以纠正。首先是我在上面提到的char*
声明中的标记名。其次,您不需要在解析器代码中%union
,因为它的内容已经插入。
解析器代码中最令人困惑的部分是在整个语法中使用命名类型语法#include "y.tab.h"
。 不要这样做。您应该正确地声明所有令牌和非终端的正确类型:
$<tag>1
(假设有一组更标准的标记名。)如果提供显式标记名,生成的解析器将使用该标记名,从而绕过类型安全检查。 (而且,显然,如果你绕过类型安全检查,在规则中使用错误的工会成员会更容易,导致谁知道后果是什么)