在 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&&b
和 b)
。请注意,在这种情况下,我得到 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
我想获取 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&&b
和 b)
。请注意,在这种情况下,我得到 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