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