在 C++ 中使用 Bison 和 Flex 检测 if 语句的条件

Detect conditions of an if statements using Bison and Flex in C++

我想获取 C++ 中 if 语句的所有条件。如果我输入 (foo&&bar&&(one&&two)),那么我想打印 foo - bar - one - two.

我已经编译了 scanner.l 和 parser.y 文件,并分别进行了测试:my yy.lex.c 有效:如果我输入 (a&&b),那么我会得到 5 个令牌:(a&&b) 随心所欲。但是,当我使用 .y 文件时,如果输入相同的输入,则会得到 a&&bb)。请注意,在这种情况下,我得到 2 个标记,因为标记 a&&b 应分为 3 个标记 a&&b。我尝试引入一个更简单的条件:(a) 然后我得到:(a) 但我想得到 (a).

不知道是我哪里做错了还是bug;我希望这是我的错。

parser.y

%{
    #include <iostream>
    #include <list>
    #include <stdio.h>
    #include <sstream>
    #include <string>

    using namespace std;

    int yylex(void);
    void yyerror(char *);

    list<string> tokenList;

    #define YYSTYPE char *
%}

%token  PAR_IZQ
        PAR_DER
        SIMBOLO
        FIN
        NADA
        AND
        OR

%start input

%%

input:

    |   input terminos
;

terminos:
        PAR_IZQ terminos PAR_DER    { }
    |   PAR_IZQ condicion PAR_DER   { }
;

condicion:
        terminos AND terminos       { }
    |   SIMBOLO AND terminos        { cout << " 1) CONDITION FOUND: " <<  << endl; }
    |   terminos AND SIMBOLO        { cout << " 2) CONDITION FOUND: " <<  << endl; }
    |   SIMBOLO AND SIMBOLO         { cout << " 3) CONDITION FOUND: " <<  << " AND " <<  << endl; }
    |   SIMBOLO                     { cout << " 4) CONDITION FOUND: " <<  << endl; }
;

%%

void yyerror(char *s) {
    fprintf(stderr, "%s\n", s);
}

int main(void) {
    yyparse();
    return 0;
}

scanner.l

%option noyywrap
%{
    #include <iostream>
    #include "parser.tab.c"
    using namespace std;
%}

%%

[a-zA-Z0-9]+  {
    yylval = yytext;
    return SIMBOLO;
}

"&&" {
    return AND;
}

"||" {
    return OR;
}

[ [=11=][=11=]] {
    return FIN;
}

"("     {
    yylval = yytext;
    return PAR_IZQ;
}

")"     {
    yylval = yytext;
    return PAR_DER;
}

.       {
    cout << "Entrada no permitida.";
    cout << endl << yytext << endl;
    exit(1);
}

%%

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include "lex.yy.c"
#include <iostream>
#include <vector>
#include <string>

using namespace std;

typedef yy_buffer_state *YY_BUFFER_STATE;
extern int yyparse();
extern YY_BUFFER_STATE yy_scan_buffer(char *, size_t);

int main(int argc, char** argv) {

    char condition[] = "(a) [=12=][=12=]";
    // note yy_scan_buffer is looking for a double null string
    yy_scan_buffer(condition, sizeof(condition));
    yyparse();
    return 0;
}

请注意,解析器的输入是一个字符串,因此我必须将其作为 yy_scan_buffer 函数的参数传递。 [=35=][=35=] 是必需的,否则程序将永远不会结束执行。控制台显示红色"syntax error",但我不知道为什么!

你知道我该如何修复它并获得我想要的代币吗?

谢谢!

PS:我正在使用 Windows 8.1、Qt creator 2.8.1、win_bison 2.7 和win_flex2.5.37.

问题是你的词法分析器 returns yytext 作为与符号标记关联的 yylval 到解析器,但 yytext 是指向词法分析器内部标记的指针缓冲区,只有在读取下一个令牌之前才有效。因此,当您稍后打印出符合您条件的标记时,您会得到半随机垃圾(因为它很快就会出现,您大多只是获得相同的原始标记缓冲区,没有终止空字符)。

您需要复制 yytext 指向的字符串,然后再将其返回给解析器:

[a-zA-Z0-9]+  {
    yylval = strdup(yytext);
    return SIMBOLO;
}

当然,您还需要跟踪何时不再需要字符串以及 free 它。

或者,由于您没有使用 %union,请将 #define for YYSTYPE 更改为

#define YYSTYPE  std::string