-1

I'm getting Segmentation fault (core dumped) for the following codes :

The lex file is as follows, 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;
    }

The yacc file is as follows,

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");
}

I've been trying for hours to figure out what is the problem. I am completely new with these and following the book "O'reilly - Lex and Yacc".

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • 4
    Don't provide you own prototype declaration of standard functions, include the correct header files instead. Also please read [this discussion about casting the result of `malloc`](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Some programmer dude Jan 13 '17 at 17:48
  • 4
    http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – melpomene Jan 13 '17 at 17:49
  • 1
    As for your problem, if you run in a debugger where does the crash happens? Is your code in the call stack? And please edit your question to include the input you provide to cause the crash. – Some programmer dude Jan 13 '17 at 17:53
  • @melpomene thanks a lot! removing the feof() worked like a charm!!! – Tahsin Tausif Jan 13 '17 at 17:58
  • @Someprogrammerdude i'm still a beginner when it comes to gdb so i really don't know how to trace the crash. – Tahsin Tausif Jan 13 '17 at 17:59
  • @user3470048 If that fixed the problem, then `yyin` was probably not initialized yet (presumably the call to `yyparse` does that?). – melpomene Jan 13 '17 at 18:02
  • 2
    You need to update your books, `yyerror(s)` this style of function declaration is discouraged for the last 20 years at least – n. m. could be an AI Jan 13 '17 at 18:03
  • @melpomene that could be it. Now i'm facing another problem, inputting same sentence twice creates an error. i should try using gdb. – Tahsin Tausif Jan 13 '17 at 18:03
  • 1
    @n.m. The book i have is from 1991. god that's old!! – Tahsin Tausif Jan 13 '17 at 18:04
  • Yeah, that's probably still using pre-standard C. The first C standard came out in 1989/1990 (ANSI/ISO version, respectively). – melpomene Jan 13 '17 at 18:05
  • I used gdb and @melpomene , you were right, (gdb) print yyin $1 = (FILE *) 0x0 so it means yyin is not getting initialized! Thanks a lot for the help! – Tahsin Tausif Jan 13 '17 at 18:09
  • 1
    You might want to consider using the book "Flex and Bison" also by Levine. It was published in 2009 and uses the GNU variants of lex and yacc. – Michael Burr Jan 13 '17 at 18:43
  • thank @MichaelBurr ! i will give it a try! – Tahsin Tausif Jan 13 '17 at 19:45
  • And when you're provided with an error message in `yyerror()`, don't just ignore it and mindlessly print `"some error'"`. Print the one you're given in the argument. – user207421 Jan 13 '17 at 23:53

1 Answers1

1

The scanner generated by (f)lex, which is the component responsible for performing the input, initializes yyin and yyout to stdin and stdout, respectively, during its initialization function. Before that, they are both NULL pointers, as a result of C's static initialization rule (which is that global pointer variables are initialized to NULL.)

The initialization function is called the first time yylex is called. (It sets a flag so that the next call to yylex does not do the initialization again. That's a very typical approach to initializing library systems; most malloc implementations and some implementations of the C stdio functions do the same thing.)

yylex is called repeatedly by yyparse, so the first call to yyparse implicitly initializes yylex. But when you write:

main(){ 
  while(!feof(yyin)){
    yyparse();
  }
}

the first use of yyin occurs before it has been initialized. Consequently, the first time the while condition is evaluated, yyin is still NULL and therefore there is no second time; the resulting segfault is fatal.

You could fix that by initializing yyin yourself, but since while (!feof(file)) is always wrong (sm), it would make more sense to put the EOF test at the end of the loop:

int main(){ 
  do yyparse(); while (!feof(yyin));
}

See this very helpful SO answer to the question Why is “while ( !feof (file) )” always wrong? for a detailed analysis.

Community
  • 1
  • 1
rici
  • 234,347
  • 28
  • 237
  • 341