5

I'm working on a Flex & Bison project. I got my flex & bison perfectly working but I'm trying to give argv as the input (yyin). So I've changed yyin so that it took the argv[1] but it's actually not working. It seem that it took the argv[1] but then i got a syntax error even if my string i suppose to work perfectly.

Here is my flex :

%{
#include "parser.hpp"
extern int yyparse();
%}

%option noyywrap


texte  [a-zA-z]+
entier [0-9]+(\.[0-9])?

%%

{entier} { yylval.num = atoi(yytext); return(NUMBER);}

"pi" return(PI);
"," return(SEP);
"(" return(OP);
")" return(CP);
"+" return(ADD);
"-" return(SUB);
"*" return(MUL);
"/" return(DIV);
"%" return (MODULO);
"sin" return(SIN);
"cos" return(COS);
"tan" return(TAN);
"acos" return(ACOS);
"asin" return(ASIN);
"atan" return(ATAN);
"sqrt" return(ROOT);
"pow" return(POW);
"exp" return(EXP);
"\n" return(END);
{texte} return(ERROR);
%%

Then my bison (i've not implemented COS SIN and other to be easiest to read):

 %defines
%{
#include <iostream>
#include <math.h>
using namespace std;
extern int yylex();
extern void yyerror(char const* msg);
%}

%union {double num;}

/* CARACTERES */
%token <num> NUMBER PI
%token OP CP SEP END

/* TRIGO */
%token COS SIN TAN
%token ACOS ASIN ATAN
/* CALCUL */
%token ADD SUB
%token MUL DIV
%token ROOT POW MODULO EXP ABS

/* CALCUL ORDER */
%left ADD SUB
%left MUL DIV

/* TRASH */
%token ERROR

%type <num> calclist exp factor term
%start calclist
%%
calclist: /* nothing */
 | calclist exp END {cout << $2 << endl;}
 ;
exp: factor
 | exp ADD factor { $$ = $1 + $3; }
 | exp SUB factor { $$ = $1 - $3; }
 ;
factor: term
 | factor MUL term { $$ = $1 * $3; }
 | factor DIV term { $$ = $1 / $3; }
 ;
term: NUMBER
 | OP exp CP {$$ = $2;}
 ;
%%



extern void yyerror(char const* msg){
  cerr << "Error " << msg << endl;
}

Then my main :

#include <iostream>
#include "parser.hpp"
#include <string.h>
using namespace std;

extern FILE *yyin;
extern int yy_scan_string(const char *);


int main(int argc, char const *argv[]) {
  /*string buf(argv[1]);
  buf.append("\0");*/
  yy_scan_string(argv[1]);
  return yyparse();
}

and finally my makefile :

all: bison flex main.cpp
    g++ parser.cpp lexer.cpp main.cpp -o parser
    rm lexer.cpp parser.cpp parser.hpp
    ./parser "(1+2)"
bison: parser.y
    bison -o parser.cpp parser.y
flex: lexer.l
    flex -o lexer.cpp lexer.l

I tried ./parser (1+2) too but i got more error. Thanks for help !

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
G.Courmont
  • 187
  • 2
  • 10

3 Answers3

4

From the Flex & Bison book (page 124):

The routines yy_scan_bytes and yy_scan_string create a buffer with a copy of the text to be scanned.

(Emphasis mine)

And

Once a string buffer is created, use yy_switch_to_buffer to tell the scanner to read from it...

The yy_scan_string only creates a buffer object that you need to explicitly use:

YY_BUFFER_STATE bp = yy_scan_string(...);  // Creates a buffer from the string
yy_switch_to_buffer(bp);                   // Use the buffer
int ret = yyparse();                       // Parse the string
yy_delete_buffer(bp);                      // Free the buffer
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thanks a lot ! Do i need to include something for YY_BUFFER_STATE ? I got an error for it and for switch to buffer too ! – G.Courmont Nov 15 '16 at 08:59
  • @G.Courmont I don't remember, it was to long ago I used Flex/Bison myself. I basically just read the linked book right now, and it doesn't say anything in the sections I read. You have to search the autogenerated header files, and other header files related to Flex/Bison installed on your system. – Some programmer dude Nov 15 '16 at 09:01
  • This answer is not correct. See the flex documentation. – rici Nov 15 '16 at 16:14
1

I finally find the answer. I juste had to change a little bit my main :

string str = argv[1];
str += '\n';
yy_scan_string(str.c_str());

Because yyin is a 0-Terminated. Hope this is gonna help other people !

G.Courmont
  • 187
  • 2
  • 10
0

You can completely restart the lexer with a file. An example:

int main(int argc, char *argv[]) {
    if (argc < 2) {
        yylineno = 1;
        yylex();
    }
    else {
        int i;
        for (i = 1; i < argc; i++) {
            FILE *f = fopen(argv[i], "r");

            // Check we opened the file correctly
            if (!f) {
                perror(argv[i]);
                return 1;
            }

            // Start next
            curfilename = argv[i];
            yyrestart(f);
            yylineno = 1;
            yylex();
            fclose(f);
        }
    }
}
James
  • 1