Adel Bouhraoua
Adel Bouhraoua

Reputation: 71

Syntax Error in compiler made with flex and bison

First of all, I'm very new to flex and bison and I really can't seem to solve this problem.

I have created both flex and bison files and it the compilation works fine here are both my flex and bison files

(ps the comments are in french) Flex:

%{
// Définitions en language C
#include"minilang.tab.h"
extern int yylval;
extern int nbrligne;
%}

    // les définitions des expressions régulières

    /*
    Définitions de la partie 
    "Liste Declarations" du language MiniLang
    qui inclut les déclarations du language Minilang
    */

chiffre [0-9]
vide [ \t]+|" "+
saut_ligne [\n]+

    // les Nombres (valeurs)
integer [- | +]?([1-9][0-9]*|0)
float [- | +]?([1-9][0-9]*|0)\.[0-9]*[1-9]
bool ("true"|"false"|"TRUE"|"FALSE")
constant integer|float

    // Définitions
varint "INT"|"int"
varfloat "FLOAT"|"float"
varbool "bool"|"BOOL"
const "CONST"|"const"
comment "{"[^}]*"}"

    // Déclarations des éléments du language

    // IDF à revoir
idf ([A-Z]([_]?[a-z0-9])*){1,11}
affectation "="
semicolon ";"
vg ","
plus "++"
minus "--"
beginmc "begin"|"BEGIN"
end "end"|"END"

    /*
    Définitions de la partie 
    "List Instructions" du language MiniLang
    qui inclut les instructions du language Minilang
    */

    // Affectation
op "+"|"-"|"*"|"/"|"&&"|"||"

    // Condition if
if "if"|"IF"|"If"
comp "=="|"<"|"<="|"<>"|">"|">="

    // For loop
for "for"|"FOR"

    // Common
paropen "("
parclose ")"
curlopen "{"
curlclose "}"

%%
    // Expression Régulière { Action C}
{chiffre} {return token_chiffre;}
{vide}
{saut_ligne} {nbrligne++;}
{integer} { yylval = atoi(yytext); return token_integer;}
{float} { yylval = atof(yytext); return token_float;}
{bool} {return token_bool;}
{varint} {return token_varint;}
{varfloat} {return token_varfloat;}
{varbool} {return token_varbool;}
{const} {return token_const;}
{comment} {return token_comment;}

{idf} {return token_idf;}

{affectation} {return token_affectation;}
{semicolon} {return token_semicolon;}
{vg} {return token_vg;}
{plus} {return token_plus;}
{minus} {return token_minus;}
{beginmc} {return token_begin;}
{end} {return token_end;}
{op} {return token_op;}
{if} {return token_if;}
{comp} {return token_comp;}
{for} {return token_for;}
{paropen} {return token_paropen;}
{parclose} {return token_parclose;}
{curlopen} {return token_curlopen;}
{curlclose} {return token_curlclose;}
{constant} {return token_constant;}
. {printf("\nErreur lexicale a la ligne %d ",nbrligne);}
%%

and bison:

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

int nbrligne=0;
int yylex();
void yyerror(const char *s);
%}

// Token definitions
%token token_chiffre
%token token_vide
%token token_integer
%token token_float
%token token_bool
%token token_varint
%token token_varfloat
%token token_varbool
%token token_const
%token token_comment
%token token_idf
%token token_affectation
%token token_semicolon
%token token_vg
%token token_plus
%token token_minus
%token token_begin
%token token_end
%token token_op
%token token_if
%token token_comp
%token token_for
%token token_paropen
%token token_parclose
%token token_curlopen
%token token_curlclose
%token token_constant

%%

Prog: DecList token_begin InstList token_end|;

DecList: Declaration DecList|Declaration | token_comment DecList | token_comment;

Declaration: ConstIntDec | ConstFloatDec | ConstBoolDec | IntDec | FloatDec | BoolDec;

ConstIntDec: token_const token_varint MultiIdfInt token_semicolon;

ConstFloatDec: token_const token_varfloat MultiIdfFloat token_semicolon;

ConstBoolDec: token_const token_varbool MultiIdfBool token_semicolon;

IntDec: token_varint MultiIdfInt token_semicolon;
FloatDec: token_varfloat MultiIdfFloat token_semicolon;
BoolDec: token_varbool MultiIdfBool token_semicolon;

MultiIdfInt: token_idf token_vg MultiIdfInt | token_idf | token_idf token_affectation token_integer MultiIdfInt ;

MultiIdfFloat: token_idf token_vg MultiIdfFloat | token_idf | token_idf token_affectation token_integer MultiIdfFloat ;

MultiIdfBool: token_idf token_vg MultiIdfBool | token_idf | token_idf token_affectation token_integer MultiIdfBool ;


InstList: Instruction InstList | Instruction | token_comment InstList | token_comment;

Instruction: Boucle | Affectation | Condition;

Affectation: token_idf token_affectation Exp token_semicolon | Incrementation;

Incrementation: token_constant token_plus | token_constant token_minus;

Exp: token_idf token_op Exp | token_idf | ExpConst;

ExpConst: token_integer token_op ExpConst | token_float token_op ExpConst | token_bool token_op ExpConst 
|   token_bool 
|   token_constant;

Condition: token_if token_paropen ExpCond token_parclose token_curlopen InstList token_curlclose;

ExpCond: token_idf token_comp token_idf 
|   token_idf token_comp token_constant
|   token_idf token_comp token_bool
|   token_constant token_comp token_idf
|   token_bool token_comp token_idf
|   token_constant token_comp token_constant
|   token_bool;

Boucle: token_for token_paropen Affectation token_vg ExpCond token_vg Incrementation token_parclose token_curlopen InstList token_curlclose;









%%

#include"lex.yy.c"
int main() {
    yyparse();
    return yylex();
}

void yyerror(const char *s){ printf("\nERROR %d\n",nbrligne); }
int yywrap(){ return 1; }

// int yywrap(void){
//  return 1;
// }

And here are the commands I ran to compile both of them and execute the compiler

flex minilang.l
bison -d minilang.y
gcc -o compiler minilang.tab.c

test.minilang is a file that I created that is supposed to be the same language this compiler is supposed to interpret here are his contents

int K_ms;
BEGIN
K_ms=16;
END

the error produced with this code is "ERROR 1" which means it happened on the first line and I don't understand where is the error in my code the language is supposed to look like this:

// List of Variable Declarations
BEGIN
// List of Instructions
END

Upvotes: 0

Views: 562

Answers (1)

rici
rici

Reputation: 241909

I'm not in front of a computer right now, so I'm going to answer a slightly different question: "How can I debug my parser?"

A lot of this is just common sense, and would apply to the use of any tool or library that you are not familiar with. But there are also some features of Flex and Bison which can be really useful.

So we can start with the most obvious advice: have the documentation easily at hand. It's quite possible that you actually do have it on your machine, if you're using a unix-like operating system. A correct flex and bison installation should include the files necessary to use the info tool. So you could try typing

info flex # or info bison

And see if that gives you the manual. If not, you can read the same docs online (although make sure your flex/bison version matches). You'll find them at

Both of these manuals have sections on debugging.

Next general advice: start small, and work your way up. Don't write several hundred lines of code using a tool you're not familiar with, and only then start testing. Start with the smallest piece which does something you can test, and test it before adding more complication. Not only will this help you solve your own problems; it will also help you describe your problem when you need to ask for help.

In the case of a parser, it's clear how to start small: start with the lexer and make sure that it splits your input into tokens as your grammar will expect.

If you're going to be using Flex with Bison, you will need to write a small part of your Bison file: just enough for Bison to produce a header file. Flex scanners require this header file because it defines the enum constants you will be returning to the parser, as well as declaring the semantic type YYSTYPE and the variable yylval, used to communicate each token's semantic value. (There's a whole chapter on semantic values in the Bison manual which explains how to declare and use token values.)

You can easily test your lexer by using the -d flag to Flex, which will cause the generated scanner to print debugging information for each pattern matched (whether or not the scanner returns a token). You can compile the scanner with -lfl; this library includes a simple main which just calls the scanner repeatedly until it reports EOF.

You should definitely do this step, because your Flex scanner has several bugs which are not related to your question but which will cause problems later. You will want to refer to the chapter on Patterns in the Flex manual.

Once your scanner is working, you can start working on your parser. Like Flex, Bison offers a debugging mechanism which will prove to be very useful. Only very minor changes are needed to use it:

  • First, add the -t (trace) flag to your Bison invocation. This will include the code to generating debugging traces. But you still need to start the traces.

  • Add the following to your main() function before you call yyparse:

    #if YYDEBUG
      yydebug = 1;
    #endif
    

    The preprocessor test is necessary because yydebug doesn't exist unless the parser was generated with the -t flag. You might want to make setting yydebug conditional on a command-line flag or environment variable so you can turn debugging on or off without recompiling.

The Bison debugging information can be a bit overwhelming at first, but it's not that complicated. It will help to have the state machine handy; Bison generates a text version if you use the -v flag. (It also can draw the state machine using Graphviz, but aside from toy grammars with only four or five productions, the graphic is basically unusable.)

Upvotes: 2

Related Questions