Bison/flex逻辑表达式无括号不起作用



当我尝试用括号执行逻辑顺序时,它可以工作,但如果没有括号,它会返回line 11: syntax error at '=='

那11行是

if c == 1 or b == 0 and not a == 0{

我已将和,或,定义为非令牌。如果我在那一行使用括号,它是有效的,但它也必须在没有括号的情况下工作。这是我的那些的解析器.y代码

| adierazpena RAND M adierazpena
{
$<adi>$ = new expressionstruct;
kodea.agOsatu($<adi>1->trueL, $<erref>3);
$<adi>$->trueL = $<adi>4->trueL;
$<adi>$->falseL = $<adi>1->falseL;
$<adi>$->falseL.insert($<adi>$->falseL.end(), $<adi>4->falseL.begin(), $<adi>4->falseL.end());
delete $<adi>1;
delete $<adi>4;
}
| adierazpena ROR M adierazpena
{
$<adi>$ = new expressionstruct;
kodea.agOsatu($<adi>1->falseL, $<erref>3);
$<adi>$->trueL = $<adi>1->trueL;
$<adi>$->trueL.insert($<adi>$->trueL.end(), $<adi>4->trueL.begin(), $<adi>4->trueL.end());
$<adi>$->falseL = $<adi>4->falseL;
delete $<adi>1;
delete $<adi>4;
}
| RNOT adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL = $<adi>2->falseL;
$<adi>$->falseL = $<adi>2->trueL;
delete $<adi>2;
}

我还将优先级设置为%left RAND RNOT ROR

我找不到任何解决方案,如有帮助,不胜感激。

如果你需要它,这就是整个语法分析器.y代码

%{
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std; 
extern int yylex();
extern int yylineno;
extern char *yytext;
void yyerror (const char *msg) {
printf("line %d: %s at '%s'n", yylineno, msg, yytext) ;
}
#include "Kodea.h"
#include "Lag.h"
Kodea kodea;
%}

/* Hemen erazagutu ikurrek zein atributu-mota izan dezaketen */
%union {
string *izena; 
string *mota;
IdLista *izenak;
expressionstruct *adi;
int erref;
skipexitstruct *jauzi;
}

/* 
Tokenak erazagutu. Honek tokens.l fitxategiarekin
bat etorri behar du.
Atributu lexikoak ere hemen erazagutu behar dira.
.izena atributua duten tokenak: 

*/
%token <izena> TID TINTEGER TFLOAT
/* Atributurik gabeko tokenak: */
%token RINT RFLOAT TASSIG TLBRACE TRBRACE TSEMIC TKOM RDO RPROGRAM RUNTIL RELSE 
%token RPROC TLPAR TRPAR TIN TIO RWHILE RFOREVER RSKIP RIF REXIT RREAD
%token TSUM TSUB TMUL TDIV TCEQ TCGT TCLT TCGE TLEOUT TCNE RPRINTLN
%token RAND ROR RNOT

/* Hemen erazagutu atributuak dauzkaten ez-bukaerakoak */
%type <adi> adierazpena
%type <izena> aldagaia
%type <mota> mota par_mota
%type <izenak> id_zerrenda id_zerrendaren_bestea
%type <erref> M 
%type <jauzi> sententzia sententzia_zerrenda

%start programa
%nonassoc TCEQ TCGT TCLT TCGE TLEOUT TCNE
%left TSUM TSUB
%left TMUL TDIV
%left RAND RNOT ROR
%%
programa : RPROGRAM TID { kodea.agGehitu("prog " + *$<izena>2); delete $<izena>2;}
erazagupenak azpiprogramen_erazagupena 
TLBRACE sententzia_zerrenda TRBRACE {kodea.agGehitu("halt "); kodea.idatzi();}
;
erazagupenak : mota id_zerrenda TSEMIC 
{kodea.erazagupenakGehitu(*$<mota>1, *$<izenak>2);delete $<izenak>2;}
erazagupenak
| /* hutsa */
;
id_zerrenda : TID id_zerrendaren_bestea
{
$<izenak>$ = new IdLista;
$<izenak>$ -> push_back(*$<izena>1);
$<izenak>$ -> insert($<izenak>$->end(), $<izenak>2->begin(), $<izenak>2->end());
delete $<izena>1;
delete $<izenak>2;
}
;
id_zerrendaren_bestea : TKOM TID id_zerrendaren_bestea
{
$<izenak>$ = new IdLista;
$<izenak>$ -> push_back(*$<izena>2);
$<izenak>$ -> insert($<izenak>$->end(), $<izenak>3->begin(), $<izenak>3->end());
delete $<izena>2;
delete $<izenak>3;
}
| /* hutsa */ {$<izenak>$ = new IdLista;}
;
mota : RINT {$<mota>$ = new std::string; *$<mota>$ = SINTEGER;}
| RFLOAT {$<mota>$ = new std::string; *$<mota>$ = SFLOAT;}
;
azpiprogramen_erazagupena : azpiprogramaren_erazagupena azpiprogramen_erazagupena
| /* hutsa */
;
azpiprogramaren_erazagupena : RPROC TID {kodea.agGehitu("proc " + *$<izena>2); delete $<izena>2;}
argumentuak erazagupenak azpiprogramen_erazagupena 
TLBRACE sententzia_zerrenda TRBRACE {kodea.agGehitu("endproc");}
;
argumentuak : TLPAR par_zerrenda TRPAR
| /* hutsa */
;
par_zerrenda : mota par_mota id_zerrenda 
{
kodea.parametroakGehitu(*$<mota>1, *$<izenak>3, *$<mota>2);
delete $<mota>1;
delete $<izenak>3;
delete $<mota>2;
}
par_zerrendaren_bestea
;                          
par_mota : TIN {$<mota>$ = new std::string; *$<mota>$ = "in";}
| TLEOUT {$<mota>$ = new std::string; *$<mota>$ = "out";}
| TIO {$<mota>$ = new std::string; *$<mota>$ = "in out";}
;
par_zerrendaren_bestea : TSEMIC mota par_mota id_zerrenda 
{
kodea.parametroakGehitu(*$<mota>2, *$<izenak>4, *$<mota>3);
delete $<mota>2;
delete $<izenak>4;
delete $<mota>3;
}
par_zerrendaren_bestea
| /* hutsa */ 
;
sententzia_zerrenda : sententzia sententzia_zerrenda
{
$<jauzi>$ = new skipexitstruct;
$<jauzi>$->skip = $<jauzi>1->skip;
$<jauzi>$->skip.insert($<jauzi>$->skip.end(), $<jauzi>2->skip.begin(), $<jauzi>2->skip.end());
$<jauzi>$->exit = $<jauzi>1->exit;
$<jauzi>$->exit.insert($<jauzi>$->exit.end(), $<jauzi>2->exit.begin(), $<jauzi>2->exit.end());
delete $<jauzi>1;
delete $<jauzi>2;
}
| /* hutsa */ {$<jauzi>$ = new skipexitstruct;}
;
sententzia : aldagaia TASSIG adierazpena TSEMIC
{ 
$<jauzi>$ = new skipexitstruct;
kodea.agGehitu(*$<izena>1 + " := " + $<adi>3->izena);
delete $<izena>1;
delete $<adi>3;
}
| RIF adierazpena M TLBRACE sententzia_zerrenda TRBRACE M TSEMIC
{ 
$<jauzi>$ = new skipexitstruct;
kodea.agOsatu($<adi>2->trueL, $<erref>3);
kodea.agOsatu($<adi>2->falseL, $<erref>7);
kodea.agOsatu($<jauzi>5->exit, $<erref>7);
$<jauzi>$->skip = $<jauzi>5->skip; 
delete $<adi>2;
}
| RWHILE RFOREVER M TLBRACE sententzia_zerrenda TRBRACE M TSEMIC
{
$<jauzi>$ = new skipexitstruct;
stringstream ss; ss << $<erref>3;
kodea.agGehitu("goto " + ss.str());
kodea.agOsatu($<jauzi>5->exit, $<erref>7);
$<jauzi>$->skip = $<jauzi>5->skip;
delete $<jauzi>5;
}
| RDO M TLBRACE sententzia_zerrenda TRBRACE RUNTIL M adierazpena RELSE M TLBRACE sententzia_zerrenda TRBRACE M TSEMIC
{
$<jauzi>$ = new skipexitstruct;
kodea.agOsatu($<adi>8->trueL, $<erref>10);
kodea.agOsatu($<adi>8->falseL, $<erref>2);
kodea.agOsatu($<jauzi>4->skip, $<erref>7);
kodea.agOsatu($<jauzi>4->exit, $<erref>14);
kodea.agOsatu($<jauzi>12->exit, $<erref>14);
$<jauzi>$->skip = $<jauzi>12->skip;
delete $<adi>8;
delete $<jauzi>4;
delete $<jauzi>12;
}
| RSKIP RIF adierazpena TSEMIC M
{
$<jauzi>$ = new skipexitstruct;
kodea.agOsatu($<adi>3->falseL, $<erref>5);
$<jauzi>$->skip = $<adi>3->trueL;
delete $<adi>3;
}
| REXIT TSEMIC
{
$<jauzi>$ = new skipexitstruct;
$<jauzi>$->exit.push_back(kodea.lortuErref());
kodea.agGehitu("goto");
}
| RREAD TLPAR aldagaia TRPAR TSEMIC
{
$<jauzi>$ = new skipexitstruct;
kodea.agGehitu("read " + *$<izena>3);
}
| RPRINTLN TLPAR aldagaia TRPAR TSEMIC
{
$<jauzi>$ = new skipexitstruct;
kodea.agGehitu("write " + $<adi>3->izena);
kodea.agGehitu("writeln");
}
;
M : /* produkzio hutsa */ { $<erref>$ = kodea.lortuErref(); }
;
aldagaia : TID {$<izena>$ = $<izena>1;}
;
adierazpena : adierazpena TSUM adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = kodea.idBerria();
kodea.agGehitu($<adi>$->izena + " := " + $<adi>1->izena + " + " + $<adi>3->izena);
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TSUB adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = kodea.idBerria();
kodea.agGehitu($<adi>$->izena + " := " + $<adi>1->izena + " - " + $<adi>3->izena);
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TMUL adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = kodea.idBerria();
kodea.agGehitu($<adi>$->izena + " := " + $<adi>1->izena + " * " + $<adi>3->izena);
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TDIV adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = kodea.idBerria();
kodea.agGehitu($<adi>$->izena + " := " + $<adi>1->izena + " / " + $<adi>3->izena);
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TCEQ adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL.push_back(kodea.lortuErref());
$<adi>$->falseL.push_back(kodea.lortuErref()+1);
kodea.agGehitu("if " + $<adi>1->izena + " = " + $<adi>3->izena + " goto");
kodea.agGehitu("goto");
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TCGT adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL.push_back(kodea.lortuErref());
$<adi>$->falseL.push_back(kodea.lortuErref()+1);
kodea.agGehitu("if " + $<adi>1->izena + " > " + $<adi>3->izena + " goto");
kodea.agGehitu("goto");
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TCLT adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL.push_back(kodea.lortuErref());
$<adi>$->falseL.push_back(kodea.lortuErref()+1);
kodea.agGehitu("if " + $<adi>1->izena + " < " + $<adi>3->izena + " goto");
kodea.agGehitu("goto");
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TCGE adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL.push_back(kodea.lortuErref());
$<adi>$->falseL.push_back(kodea.lortuErref()+1);
kodea.agGehitu("if " + $<adi>1->izena + " >= " + $<adi>3->izena + " goto");
kodea.agGehitu("goto");
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TLEOUT adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL.push_back(kodea.lortuErref());
$<adi>$->falseL.push_back(kodea.lortuErref()+1);
kodea.agGehitu("if " + $<adi>1->izena + " <= " + $<adi>3->izena + " goto");
kodea.agGehitu("goto");
delete $<adi>1;
delete $<adi>3;
}
| adierazpena TCNE adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL.push_back(kodea.lortuErref());
$<adi>$->falseL.push_back(kodea.lortuErref()+1);
kodea.agGehitu("if " + $<adi>1->izena + " != " + $<adi>3->izena + " goto");
kodea.agGehitu("goto");
delete $<adi>1;
delete $<adi>3;
}
| aldagaia
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = *$<izena>1;
delete $<izena>1;
}
| TINTEGER
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = *$<izena>1;
delete $<izena>1;
}
| TFLOAT
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = *$<izena>1;
delete $<izena>1;
}
| TLPAR adierazpena TRPAR
{
$<adi>$ = new expressionstruct;
$<adi>$->izena = $<adi>2->izena;
$<adi>$->trueL = $<adi>2->trueL;
$<adi>$->falseL = $<adi>2->falseL;
delete $<izena>2;
}
| adierazpena RAND M adierazpena
{
$<adi>$ = new expressionstruct;
kodea.agOsatu($<adi>1->trueL, $<erref>3);
$<adi>$->trueL = $<adi>4->trueL;
$<adi>$->falseL = $<adi>1->falseL;
$<adi>$->falseL.insert($<adi>$->falseL.end(), $<adi>4->falseL.begin(), $<adi>4->falseL.end());
delete $<adi>1;
delete $<adi>4;
}
| adierazpena ROR M adierazpena
{
$<adi>$ = new expressionstruct;
kodea.agOsatu($<adi>1->falseL, $<erref>3);
$<adi>$->trueL = $<adi>1->trueL;
$<adi>$->trueL.insert($<adi>$->trueL.end(), $<adi>4->trueL.begin(), $<adi>4->trueL.end());
$<adi>$->falseL = $<adi>4->falseL;
delete $<adi>1;
delete $<adi>4;
}
| RNOT adierazpena
{
$<adi>$ = new expressionstruct;
$<adi>$->trueL = $<adi>2->falseL;
$<adi>$->falseL = $<adi>2->trueL;
delete $<adi>2;
}
;
%%

我假设当你说"如果我在那一行使用括号;,你的意思是,以下工作如预期:

(c == 1) or (b == 0) and not (a == 0)

这是因为您的优先级声明顺序错误。

您有以下内容:

%nonassoc TCEQ TCGT TCLT TCGE TLEOUT TCNE
%left TSUM TSUB
%left TMUL TDIV
%left RAND RNOT ROR

这使得andornot==(以及其他比较运算符(更强地结合。相比之下,把*放在+之后是正确的,因为乘法比加法结合得更强。

因为or比比较更严格地保留自变量,所以表达式c == 1 or b == 0 and not a == 0被分组为c == (1 or b) == (0 and (not a)) == 0,这是无意义的。这也是一个语法错误,因为您已经正确地将==声明为非关联的。

这些运算符应该位于优先级层次结构的开头,而不是末尾,因为它们需要更松散地绑定。此外,您可能应该遵守通常的约定,其中andor结合得更紧密。(因为编写a > 0 and a < 10 or b > 0 and b < 10这样的逻辑表达式很常见。(所以我建议将其更改为:

%left ROR
%left RAND
%left RNOT
%nonassoc TCEQ TCGT TCLT TCGE TLEOUT TCNE
%left TSUM TSUB
%left TMUL TDIV

有些语言赋予not与其他一元运算符相同的优先级,但很明显,您希望not a == 0表示not (a == 0)(即a ≠ 0(。在C++中,! a == 0将被分组为(!a) == 0,这也意味着在应用整数和布尔值之间的转换后的a ≠ 0,但这对于与0以外的数字进行比较具有不同的意义。

最新更新