Search code examples
cbisonflex-lexer

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.


Solution

  • 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.