skip to Main Content

how to create a simple calculator for sum two numbers using flex, bison and cmake?
i try understand flex and bison (studying both), I still don’t know how to use them, and I would like a practical example of how to compile (with cmake) a simple project for me to study.

I found an example calculator and an example from cmake, but I can’t compile to test and be able to study and understand. Below has a failed attempt to compile.

This code is available in GitHub

using

find_package (BISON REQUIRED)
find_package (FLEX REQUIRED)

flex_target
bison_target

CMakeFiles.txt

cmake_minimum_required(VERSION 3.7)
project(lesson)


set(CMAKE_CXX_STANDARD 11)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

find_package(BISON REQUIRED)
find_package(FLEX REQUIRED)


bison_target(lesson-parser
        calc-parser.y
        ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.cpp
        )

flex_target(lesson-scanner
        calc-scanner.l
        ${CMAKE_CURRENT_BINARY_DIR}/scanner.tab.cpp
        )
add_executable(lesson ${BISON_MyParser_OUTPUTS} ${FLEX_MyScanner_OUTPUTS} main.cpp)
add_flex_bison_dependency(lesson-scanner lesson-parser)

calc-parser.y

/* Gramatica: {Vt, Vn, P, S}
 * Vt = {INTEGER, NEWLINE, +, -, *, /, (, )}
 * Vn = {line, term, expr}
 * P = {
 *      line -> epsilon
 *      line -> term
 *      term -> newline
 *      term -> expr newline
 *      expr -> intnumer
 *      expr -> expr + expr
 *      expr -> expr - expr
 *      expr -> expr * expr
 *      expr -> expr / expr
 *      expr -> (expr)
 *      expr -> -expr
 *     }
 * S = line
 */

%{
#include <stdio.h>
int intval;
extern char *yytext;
%}


%token INTEGER, NEWLINE

%left '+' '-'
%left '*' '/'
%nonassoc UMINUS

%start line   /* simbolo sentencial */

%%
line:
    | line term
    ;

term: NEWLINE
    | expr NEWLINE   {printf("%dn", $1);}
    | error NEWLINE  {yyerror;}
    ;

expr: INTEGER {$$ = intval;}
     | expr '+' expr  {$$ = $1 + $3;}
     | expr '-' expr  {$$ = $1 - $3;}
     | expr '*' expr  {$$ = $1 * $3;}
     | expr '/' expr  {if($3) $$ = $1 / $3;
                       else {
                             printf("Divide by zero");
                             yyerror;
                            }
                      }
     | '(' expr ')' {$$ = $2;}
     | '-' expr %prec UMINUS {$$ = - $2;}
     ;

%%

yyerror(s)
char *s;
{
printf("Oops: %s at symbol %cn", s, yytext[0]);
}

calc-scanner.l

%{
#include "y.tab.h"
extern int intval;
%}
integer [0-9]+
nl      n

%%
[ t]+  ;
{integer}    {sscanf(yytext, "%d", &intval);  return INTEGER;}
{nl}         {return NEWLINE;}
.            {return yytext[0];}
%%

Parser.h

#ifndef LESSON_PARSER_H
#define LESSON_PARSER_H

namespace Test {

    class Parser {
    public:
        static int parser();
    };
}

#endif //LESSON_PARSER_H

Parser.cpp

#include "Parser.h"

int Test::Parser::parser() {
    return yyparse();
}

main.cpp

#include <iostream>
#include "Parser.h"

int main(int argc, char **argv) {
    return Test::Parser::parser();
}

I try call the "Test::Parser::parser()" to analyze the input.
The compiler log error is:

====================[ Build | all | Debug-Debian ]==============================
/usr/bin/cmake --build /tmp/tmp.SIGMymeLDv/cmake-build-debug-debian --target all -- -j 4
[ 66%] Building CXX object CMakeFiles/lesson.dir/Parser.cpp.o
[ 66%] Building CXX object CMakeFiles/lesson.dir/main.cpp.o
/tmp/tmp.SIGMymeLDv/Parser.cpp: In static member function 'static int Test::Parser::parser()':
/tmp/tmp.SIGMymeLDv/Parser.cpp:8:12: error: 'yyparse' was not declared in this scope
     return yyparse();
            ^~~~~~~
/tmp/tmp.SIGMymeLDv/Parser.cpp:8:12: note: suggested alternative: 'parser'
     return yyparse();
            ^~~~~~~
            parser
make[2]: *** [CMakeFiles/lesson.dir/build.make:76: CMakeFiles/lesson.dir/Parser.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/lesson.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

2

Answers


  1. Chosen as BEST ANSWER

    The problem was in my cmake at add_executable, the below code do not exist:

    $ {BISON_MyParser_OUTPUTS} $ {FLEX_MyScanner_OUTPUTS} 
    

    The correct is:

    $ {BISON_lesson-parser_OUTPUTS} $ {FLEX_lesson-scanner_OUTPUTS}
    

    The code is updated in github


  2. If you want to use yyparse in Parser.cpp, then you need a declaration for it to be visible in Parser.cpp. Clearly, there is no such declaration.

    yyparse() is declared in the bison-generated header, so #including that in Parser.cpp will likely solve your problem.

    FWIW, Parser.cpp does not appear to have been extracted from either of the projects you mentioned in your original question. Evidently, not mentioning its existence made your original question much harder to answer. This is why we always request that questions include a minimal but complete program which exhibits the problem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search