在以下 lex/yacc 个文件中收到分段错误(核心已转储)。他们怎么了?
Receiving Segmentation fault (core dumped) in the following lex/yacc files. What is wrong with them?
我遇到以下代码的分段错误(核心已转储):
lex文件如下,
test.l :
%{
#include "y.tab.h"
#define LOOKUP 0
int state;
int add_word(int type, char *word);
int lookup_word(char *word);
%}
%%
\n {state = LOOKUP;}
\.\n {state = LOOKUP;
return 0;
}
^verb {state = VERB;}
^adj {state = ADJECTIVE;}
^adv {state = ADVERB;}
^noun {state = NOUN;}
^prep {state = PREPOSITION;}
^pron {state = PRONOUN;}
^conj {state = CONJUNCTION;}
[a-zA-Z]+ {
if(state != LOOKUP){
add_word(state, yytext);
}else{
switch(lookup_word(yytext)){
case VERB: return(VERB);
case ADJECTIVE: return(ADJECTIVE);
case ADVERB: return(ADVERB);
case NOUN: return(NOUN);
case PREPOSITION: return(PREPOSITION);
case PRONOUN: return(PRONOUN);
case CONJUNCTION: return(CONJUNCTION);
default:
printf("%s: don't recog\n",yytext);
}
}
}
. ;
%%
struct word{
char *word_name;
int word_type;
struct word *next;
};
struct word *word_list;
extern void *malloc();
int add_word(int type, char *word){
struct word *wp;
if(lookup_word(word) != LOOKUP){
printf("word %s already defined\n", word);
return 0;
}
wp = (struct word *) malloc(sizeof(struct word));
wp-> next = word_list;
wp-> word_name = (char*) malloc(strlen(word)+1);
strcpy(wp->word_name, word);
wp->word_type = type;
word_list = wp;
return 1;
}
int lookup_word(char *word){
struct word *wp = word_list;
for(; wp; wp = wp->next){
if(strcmp(wp->word_name, word) == 0)
return wp->word_type;
}
return LOOKUP;
}
yacc文件如下,
test.y:
%{
#include <stdio.h>
%}
%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION
%%
sentence: subject VERB object {printf("sentence is valid\n");}
;
subject: NOUN
| PRONOUN
;
object: NOUN
;
%%
extern FILE *yyin;
main(){
while(!feof(yyin)){
yyparse();
}
}
yyerror(s)
{
fprintf(stderr, "some error\n");
}
我已经尝试了几个小时来找出问题所在。我对这些完全陌生,并且正在阅读这本书 "O'reilly - Lex and Yacc"。
(f)lex生成的扫描器,负责执行输入的组件,将yyin
和yyout
分别初始化为stdin
和stdout
,在其初始化功能期间。在此之前,由于C的静态初始化规则(即全局指针变量被初始化为NULL),它们都是NULL指针。
第一次调用时调用初始化函数yylex
。 (它设置了一个标志,以便下一次调用 yylex
不会再次进行初始化。这是初始化库系统的一种非常典型的方法;大多数 malloc
实现和 C stdio
函数做同样的事情。)
yylex
被 yyparse
重复调用,所以第一次调用 yyparse
隐式初始化 yylex
。但是当你写:
main(){
while(!feof(yyin)){
yyparse();
}
}
yyin
的首次使用发生在它被初始化之前。因此,第一次评估 while
条件时,yyin
仍然是 NULL
,因此没有第二次;由此产生的段错误是致命的。
您可以通过自己初始化 yyin
来解决这个问题,但是由于 while (!feof(file))
总是错误的 (sm),所以将在循环的 end 处进行 EOF 测试:
int main(){
do yyparse(); while (!feof(yyin));
}
参见this very helpful SO answer问题为什么“while ( !feof (file) )
”总是错误的?进行详细分析。
我遇到以下代码的分段错误(核心已转储):
lex文件如下, test.l :
%{
#include "y.tab.h"
#define LOOKUP 0
int state;
int add_word(int type, char *word);
int lookup_word(char *word);
%}
%%
\n {state = LOOKUP;}
\.\n {state = LOOKUP;
return 0;
}
^verb {state = VERB;}
^adj {state = ADJECTIVE;}
^adv {state = ADVERB;}
^noun {state = NOUN;}
^prep {state = PREPOSITION;}
^pron {state = PRONOUN;}
^conj {state = CONJUNCTION;}
[a-zA-Z]+ {
if(state != LOOKUP){
add_word(state, yytext);
}else{
switch(lookup_word(yytext)){
case VERB: return(VERB);
case ADJECTIVE: return(ADJECTIVE);
case ADVERB: return(ADVERB);
case NOUN: return(NOUN);
case PREPOSITION: return(PREPOSITION);
case PRONOUN: return(PRONOUN);
case CONJUNCTION: return(CONJUNCTION);
default:
printf("%s: don't recog\n",yytext);
}
}
}
. ;
%%
struct word{
char *word_name;
int word_type;
struct word *next;
};
struct word *word_list;
extern void *malloc();
int add_word(int type, char *word){
struct word *wp;
if(lookup_word(word) != LOOKUP){
printf("word %s already defined\n", word);
return 0;
}
wp = (struct word *) malloc(sizeof(struct word));
wp-> next = word_list;
wp-> word_name = (char*) malloc(strlen(word)+1);
strcpy(wp->word_name, word);
wp->word_type = type;
word_list = wp;
return 1;
}
int lookup_word(char *word){
struct word *wp = word_list;
for(; wp; wp = wp->next){
if(strcmp(wp->word_name, word) == 0)
return wp->word_type;
}
return LOOKUP;
}
yacc文件如下,
test.y:
%{
#include <stdio.h>
%}
%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION
%%
sentence: subject VERB object {printf("sentence is valid\n");}
;
subject: NOUN
| PRONOUN
;
object: NOUN
;
%%
extern FILE *yyin;
main(){
while(!feof(yyin)){
yyparse();
}
}
yyerror(s)
{
fprintf(stderr, "some error\n");
}
我已经尝试了几个小时来找出问题所在。我对这些完全陌生,并且正在阅读这本书 "O'reilly - Lex and Yacc"。
(f)lex生成的扫描器,负责执行输入的组件,将yyin
和yyout
分别初始化为stdin
和stdout
,在其初始化功能期间。在此之前,由于C的静态初始化规则(即全局指针变量被初始化为NULL),它们都是NULL指针。
第一次调用时调用初始化函数yylex
。 (它设置了一个标志,以便下一次调用 yylex
不会再次进行初始化。这是初始化库系统的一种非常典型的方法;大多数 malloc
实现和 C stdio
函数做同样的事情。)
yylex
被 yyparse
重复调用,所以第一次调用 yyparse
隐式初始化 yylex
。但是当你写:
main(){
while(!feof(yyin)){
yyparse();
}
}
yyin
的首次使用发生在它被初始化之前。因此,第一次评估 while
条件时,yyin
仍然是 NULL
,因此没有第二次;由此产生的段错误是致命的。
您可以通过自己初始化 yyin
来解决这个问题,但是由于 while (!feof(file))
总是错误的 (sm),所以将在循环的 end 处进行 EOF 测试:
int main(){
do yyparse(); while (!feof(yyin));
}
参见this very helpful SO answer问题为什么“while ( !feof (file) )
”总是错误的?进行详细分析。