Emarth
Emarth

Reputation: 47

Bison says that start symbol does not derive any sentence

I'm writting basic compiler and I got stuck preatty early. When I try to run my bison file it throws error (it's below) I have no idea why it does and have been struggling with it for quite some time.

ERROR:

compiler/parser.y: warning: 9 nonterminals useless in grammar [-Wother]
compiler/parser.y: warning: 32 rules useless in grammar [-Wother]
compiler/parser.y:34.1-7: fatal error: start symbol program does not derive any sentence
 program            :   DECLARE declaration IN commands END

FLEX:

%option noyywrap
%{
    #include <stdio.h>
    #include "parser.tab.h"
%}

NUMBER          [0-9]+
PID                 [_a-z]+

WHITESPACE  [ \t\r]+

%x COMMENT
%%

<INITIAL>{
"["                     BEGIN(COMMENT);

\n                      yylineno++;
{WHITESPACE}

{NUMBER}            {
                                printf("Number: %s\n", yytext);
                                yylval.ival = (char*) strdup(yytext);
                                return NUM;
                            }

{PID}                   {
                                printf("PID: %s\n", yytext);
                                yylval.sval = (char*) strdup(yytext);
                                return PID;
                            }

":="                    return ASSIGN;

"+"                     return ADD;
"-"                     return SUB;
"*"                     return MUL;
"/"                     return DIV;
"%"                     return MOD;

"="                     return EQ;
"!="                    return NEQ;
"<"                     return LT;
">"                     return GT;
"<="                    return LE;
">="                    return GE;

")"                     return R_BRACKET;
"("                     return L_BRACKET;
";"                     return SEMICOLON;
":"                     return COLON;


"DECLARE"           return DECLARE;
"IN"                    return IN;
"END"                   return END;

"IF"                    return IF;
"ELSE"              return ELSE;
"ENDIF"             return ENDIF;

"WHILE"             return WHILE;
"DO"                    return DO;
"ENDWHILE"      return ENDWHILE;
"ENDDO"             return ENDDO;

"FOR"                   return FOR;
"FROM"              return FROM;
"TO"                    return TO;
"DOWNTO"            return DOWNTO;
"ENDFOR"            return ENDFOR;

"READ"              return READ;
"WRITE"             return WRITE;
}

<COMMENT>{
"]"                     BEGIN(INITIAL);
[^\n]+\n            yylineno++;
}

%%

BISON:

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    extern int yylineno;

    int yylex(void);
    void yyerror(const char *);

    int error = 0;
%}

%union{
    char* sval;
    char* ival;
}

%token <sval> DECLARE /* Declarations block */
%token <sval> IN END /* Code block */
%token <sval> IF THEN ELSE ENDIF /* Conditional block */
%token <sval> WHILE DO ENDWHILE ENDDO /* While-do and Do-while loop block */
%token <sval> FOR FROM TO DOWNTO ENDFOR /* For loop block */
%token <sval> READ WRITE
%token <sval> ASSIGN
%token <sval> ADD SUB MUL DIV MOD /* Arithmetic operators */
%token <sval> EQ NEQ LT GT LE GE /* Boolean operators */
%token <sval> L_BRACKET R_BRACKET SEMICOLON COLON /* Symbols */
%token <ival> NUM
%token <sval> PID

%%

program         :   DECLARE declaration IN commands END
                        ;

declaration :   declaration PID SEMICOLON
                        |   declaration PID L_BRACKET NUM COLON NUM R_BRACKET SEMICOLON
                        ;

commands        :   commands command
                        |   command
                        ;

command         :   id ASSIGN expression SEMICOLON
                        |   IF condition THEN commands ELSE commands ENDIF
                        |   IF condition THEN commands ENDIF
                        |   WHILE condition DO commands ENDWHILE
                        |   DO commands WHILE condition ENDDO
                        |   FOR PID FROM value TO value DO commands ENDFOR
                        |   FOR PID FROM value DOWNTO value DO commands ENDFOR
                        |   READ id SEMICOLON
                        |   WRITE value SEMICOLON
                        ;

expression  :   value
                        |   value ADD value
                        |   value SUB value
                        |   value MUL value
                        |   value DIV value
                        |   value MOD value
                        ;

condition       :   value EQ value
                        |   value NEQ value
                        |   value LT value
                        |   value GT value
                        |   value LE value
                        |   value GE value
                        ;

value               :   NUM
                        |   id
                        ;

id                  :   PID
                        |   PID L_BRACKET PID R_BRACKET
                        |   PID L_BRACKET NUM R_BRACKET
                        ;

%%

void yyerror(const char *msg) {
    fprintf(stderr, "Compiling error: %s\n", msg);
}

In case you're wondering, I run main function from another file but I don't think that is the problem.

Upvotes: 1

Views: 1382

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12708

Normally, when bison says that, it is complaining about the grammar you have feed it with. That error message means that with that grammar it is impossible to build a valid sentence, consisting only of terminal symbols. Your grammar must be patched to be able to build syntax trees that have in the leaves only terminal symbols. If you check that, you'll find that it is actually impossible to build a parse tree that has only terminal symbols in the leaves. Try and watch for yourself. This happens with this simple grammar.

sentence: '*' sentence
    | '(' sentence ')' ;

you will see that all parse trees you build for sentence always have a sentence as one of its leaves, so it's impossible to build a valid sentence in that language that has only terminal symbols.

The technical details of your concrete problem are discussed in other answer, so I'll not repeat them here (Bison uses the first rule you write in the grammar to use as root of the syntactic tree, by default, in your case is declaration, and not program)

Anyway, if you got that error, probably this is not the only problem you are having. If you try bison with option --report and --report-file (see manpage) you'll get a more detailed info about the rule that is making it to fail.

edit

after looking at your code, you expand declaration as declaration and more things in all the alternatives you give for declaration This can never generate a declaration of only terminal symbols, because as you expand, there's always a declaration to expand.

Upvotes: 0

melpomene
melpomene

Reputation: 85897

Your grammar says to have a program, you must have a declaration:

program         :   DECLARE declaration ...

And the only way to get a declaration is these two rules

declaration :   declaration ...
                    |   declaration ...

But both of those require you to already have a declaration. Since you start out with nothing, and you can only get a declaration if you already have one, you can never have any declarations.

Therefore you can never parse a program.

Upvotes: 3

Related Questions