1
votes

I am working on designing a lexical and syntax analyzer for a simple programming language. Here is my flex .l file:

%{
#include <cstdio>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
#define YY_DECL extern "C" int yylex()
#include "littleDuck.tab.h" 
int line_num = 1;
%}
id      [a-zA-Z][a-zA-Z0-9]*
cteI    [0-9]+
not     (<)(>)
cteF    {cteI}(\.{cteI}((e|E)("+"|"-")?{cteI})?)?
ctestring   (\".*\")

%%

[ \t]   ;
program {return PROGRAM;}
var     {return VAR;}
print   {return PRINT;}
"else"  {return ELSE;}
"if"    {return IF;}
{id}    {return ID;}
\=      {return '=';}
\<      {return '<';}
\>      {return '>';}
{not}   {return NOT;}
\+      {return '+';}
\-      {return '-';}
\/      {return '/';}
\*      {return '*';}
\:      {return ':';}
\,      {return ',';}
\;      {return ';';}
\{      {return '{';}
\}      {return '}';}
\(      {return '(';}
\)      {return ')';}
{cteI}  {yylval.ival = atoi(yytext); return INT;}
{cteF}  {yylval.fval = atof(yytext); return FLOAT;}
{ctestring} {yylval.sval = strdup(yytext); return STRING;}
\n      {++line_num;}
.       ;

%%

This file is being compiled correctly by flex, although I'm not completely sure if I can summarize some terms. My real problem comes when compiling my bison file. I am doing it from a Ubuntu terminal by entering this:

gabriel@virtualbox:~/Lenguajes/flexBison$ bison -d littleDuck.y

It returns 22 nonterminals useless in grammar and 41 rules useless in grammar. My bison file is the next:

%{
#include <cstdio>
#include <iostream>
using namespace std;

extern "C" int yylex();
extern "C" int yyparse();
extern "C" FILE *yyin;
extern int line_num;

void yyerror(const char *s);
%}

%union{
    int ival;
    float fval;
    char *sval;
}

%token ID NOT PROGRAM VAR PRINT IF ELSE

%token <ival> INT
%token <fval> FLOAT
%token <sval> STRING


%%
programa:
    PROGRAM ID ':' vars_1
    ;
vars_1:
    VAR
    ;
vars:
    VAR ID id_1
    ;
id_1:   
    ',' id_1
    | ':' tipo tipo_1
    ;
tipo:
    INT
    | FLOAT
    ;
tipo_1:
    /* empty */
    ID id_1
    ;
bloque:
    '{' e1
    ;
e1:
    estatuto e2
    | e2
    ;
e2:
    estatuto e2
    | '}'
    ;
estatuto:
    asignacion
    | condicion
    | escritura
    ;
asignacion:
    ID '=' expresion ';'
    ;
expresion:
    exp exp_1
    ;
exp:
    termino exp_2
    ;
exp_1:
    /* empty */
    | '>' exp
    | '<' exp
    |NOT exp
    ;
exp_2:
    '+' exp
    | '-' exp
    ;
escritura:
    PRINT '(' esc_1
    ;
esc_1:
    expresion esc_2
    | STRING esc_2
    ;
esc_2:
    ',' esc_1
    | ')' ';'
    ;
condicion:
    IF '(' expresion ')' bloque cond
    ;
cond:
    ';'
    | ELSE bloque ';'
    ;
termino:
    factor term
    ;
term:
    '*' termino
    | '/' termino
    ;
var_cte:
    ID
    | INT
    | FLOAT
    ;
factor:
    '(' expresion ')'
    | var_cte
    | '+' var_cte
    | '-' var_cte
    ;

%%
main() {
    FILE *myfile = fopen("testFile", "r");
    if (!myfile) {
        cout << "I can't open file" << endl;
        return -1;
    }
    yyin = myfile;

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

}

void yyerror(const char *s) {
    cout << "Yikes! Parse error on line " << line_num << "! Message: " << s << endl;
    exit(-1);
}

Why are warnings being generated and how can I get rid of them? Sorry for posting complete programs, but I think all information is important as flex file shows what tokens are being generated and bison file has all grammar rules.

2
might help to show some of the errorsPreet Sangha
littleDuck.y: warning: 22 nonterminals useless in grammar littleDuck.y: warning: 41 rules useless in grammar littleDuck.y:34.1-4: warning: nonterminal useless in grammar: vars littleDuck.y:35.16-19: warning: nonterminal useless in grammar: id_1 littleDuck.y:39.15-18: warning: nonterminal useless in grammar: tipo Those are some of the errors. Almost all of them are the same, with the argument changing every time.gabrielbaca
If they are useless, remove them. If you actually need to use them, then there are mistakes in your grammar.leppie
You are not using vars and that whole tree becomes useless.leppie
@gabrielbaca: it's useless because it cannot be derived from the start production (programa).rici

2 Answers

1
votes

Your grammar is essentially just:

programa:
    PROGRAM ID ':' vars_1
    ;
vars_1:
    VAR
    ;

which means that the only valid program it will accept is

program id : var

where id might be any valid identifier. Anything else will be a syntax error.

All the rest of the rules are unreachable and useless, as there is no way to reach them from programa. So bison is telling you that you might as well just delete them.

What you probably want is to add some other programa or vars_1 rule that leads to the rest of the rules so as to actually parse the language you want

-1
votes

Some grammar was indeed incorrect or with missing symbols. I rewrote my grammar and it worked correctly, only pointing out there were 3 shift-reduce. I added left associativity to tokens doing the next:

%left '*' '/'
%left '+' '-'

Also I did not add a token for reserved words "int" and "float", only having those for int and float constants. This was obviously a huge problem, as I could not declare any variable. I added them and replaced the token for constants with FLOATC and INTC. This was added on lexical file as well as grammar file.