首页 > 解决方案 > 如何使用 flex、bison 和 cmake 创建一个简单的计算器来计算两个数字的和?

问题描述

如何使用 flex、bison 和 cmake 创建一个简单的计算器来计算两个数字的和?我尝试了解 flex 和 bison(两者都学习),但我仍然不知道如何使用它们,我想要一个如何编译(使用 cmake)一个简单项目供我学习的实际示例。

我从 cmake找到了一个示例计算器和一个示例,但我无法编译测试并能够学习和理解。下面有一个失败的编译尝试。

此代码在GitHub中可用

使用

find_package (BISON REQUIRED) find_package (FLEX REQUIRED)

flex_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("%d\n", $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 %c\n", 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];}
%%

解析器.h

#ifndef LESSON_PARSER_H
#define LESSON_PARSER_H

namespace Test {

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

#endif //LESSON_PARSER_H

解析器.cpp

#include "Parser.h"

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

主文件

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

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

我尝试调用“Test::Parser::parser()”来分析输入。编译器日志错误是:

====================[ 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

标签: cmakebisonflex-lexeryacc

解决方案


问题出在我在 add_executable 的 cmake 中,以下代码不存在:

$ {BISON_MyParser_OUTPUTS} $ {FLEX_MyScanner_OUTPUTS} 

正确的是:

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

代码在github更新


推荐阅读