我一直在尝试将按位运算符添加到给我的前缀/中缀/后缀计算器中,但由于某些原因,我无法使用<<识别运算符">>“"**”。我四处寻找了一些有类似问题的人,特别是这个问题yacc/bison tokens error. '>>>' and '>>' both assigned number 62,但还没有找到一个有效的解决方案。
我的lex文件
%{
#include "zcalc.h"
#include <math.h>
int ch;
int flag = 0;
#define NAME 257
#define SEMISYM 268
#define COMMASYM 269
#define LPARSYM 270
#define RPARSYM 271
#define EQSYM 272
#define PLUSSYM 273
#define MULTSYM 274
#define ASGNSYM 275
#define MINUSSYM 276
#define NUMBER 277
#define TILDE 278
/*New stuff I added*/
#define BITAND 279
#define BITOR 280
#define BITXOR 281
/*#define BITNOT 282*/
#define LSHIFT 283
#define RSHIFT 284
#define POWER 285
void yyerror( char *mesg ); /* yacc error checker */
/* definitions for lex analyzer */
letter [A-Za-z]
digit [0-9]+
ident {letter}({letter}|{digit})*
ws [ \t\n]+
other .
%%
{ws} ; /*---- Tokens and Actions---- */
/*New Stuff*/
"&" return BITAND;
"|" return BITOR;
"^" return BITXOR;
"<<" return LSHIFT;
">>" return RSHIFT;
"**" return POWER;
"//".* ;
";" return SEMISYM;
"," return COMMASYM;
"(" return LPARSYM;
")" return RPARSYM;
"==" return EQSYM;
"+" return PLUSSYM;
"*" return MULTSYM;
"=" return ASGNSYM;
"-" return MINUSSYM;
"~" return TILDE;
/*New Stuff
"&" return BITAND;
"|" return BITOR;
"^" return BITXOR;
"<<" return LSHIFT;
">>" return RSHIFT;
"**" return POWER;*/
{ident} {
return NAME;
}
{digit} {
return NUMBER;
}
"$" { return 0; }
{other} ; /* ignore other stuff */
%%
void yyerror( char *mesg ); /* yacc error checker */
/* yacc error function */
void yyerror( char *mesg ) {
flag = 1;
printf("%s \n" , mesg);
}
int main() {
printf("Lex \t\tToken\t\t\n"); /* header on columns */
printf("----------------------------\n");
do
{
ch = yylex();
if (ch == SEMISYM)
printf("%s\t\tSEMICOLON ", yytext);
else if (ch == COMMASYM)
printf("%s\t\tCOMMA ", yytext);
else if (ch == LPARSYM)
printf("%s\t\tL_PARENTHESIS ", yytext);
else if (ch == RPARSYM)
printf("%s\t\tR_PARENTHESIS ", yytext);
else if (ch == EQSYM)
printf("%s\t\tEQ_OP ", yytext);
else if (ch == PLUSSYM)
printf("%s\t\tPLUS_OP ", yytext);
else if (ch == MULTSYM)
printf("%s\t\tMULT_OP ", yytext);
else if (ch == ASGNSYM)
printf("%s\t\tASSIGNMENT_STMT ", yytext);
else if (ch == MINUSSYM)
printf("%s\t\tMINUS_OP ", yytext);
else if (ch == NUMBER)
printf("%s\t\tNUMBER ", yytext);
else if (ch == NAME)
printf("%s\t\tNAME\t\t", yytext);
else if (ch == TILDE)
printf("%s\t\tTILDE\t\t", yytext);
else
printf("%c ",ch);
printf("\n"); /* end check token read */
}
while(ch != 0); /* read until end of file */
return 0;
}
int yywrap() {
return 1;
}
%}
和我的yacc文件
%{
#include "zcalc.h"
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int flag = 0;
void yyerror( char *mesg ); /* yacc error checker */
%}
%union {
double dval;
struct symtab *symp;
}
%token <symp> NAME
%token <dval> NUMBER
// %token LSHIFT
// %token RSHIFT
%token POWER
%left '-' '+'
//%left "**"
%left '*' '/'
//%left LSHIFT RSHIFT
//%left POWER
%type <dval> expression
%%
statement_list: statement '\n'
| statement_list statement '\n'
statement: NAME '=' expression { $1->value = $3; }
| expression { printf("= %g\n", $1); }
expression: '+' expression expression { $$ = $2 + $3; }
| '-' expression expression { $$ = $2 - $3; }
| POWER expression expression { $$ = $3; }
| '*' expression expression { $$ = $2 * $3; }
| '/' expression expression { $$ = $2 / $3; }
| '&' expression expression { $$ = (int)$2 & (int)$3; }
| '|' expression expression { $$ = (int)$2 | (int)$3; }
| '^' expression expression { $$ = (int)$2 ^ (int)$3; }
| '<' '<' expression expression { $$ = (int)$3 << (int)$4; }
| '>' '>' expression expression { $$ = (int)$3 >> (int)$4; }
//| "**" expression expression { $$ = pow($2, $3); }
| '~' expression { $$ = ~ (int)$2; }
| '(' expression ')' { $$ = $2; }
| NUMBER
| NAME { $$ = $1->value; }
%%
struct symtab * symlook( char *s ) {
char *p;
struct symtab *sp;
for(sp = symtab; sp < &symtab[NSYMS]; sp++) {
/* is it already here? */
if (sp->name && !strcmp(sp->name, s))
return sp;
/* is it free */
if (!sp->name) {
sp->name = strdup(s);
return sp;
}
/* otherwise continue to the next */
}
yyerror("Too many symbols...\n");
exit(1);
}
void addfunc( char *name, double (*func)() ) {
struct symtab *sp = symlook(name);
sp->funcptr = func;
}
/* yacc error function */
void yyerror( char *mesg ) {
flag = 1;
printf("%s \n" , mesg);
}
int main() {
yyparse();
return 0;
}
我已经在头文件中摆弄了定义和规则的位置,但这似乎不起作用。我可以使用'<‘'<’让"<<“和">>”正常工作,但是它抛出了参数计数,看起来更像是一种权宜之计,而不是一个适当的解决方案。谢谢你的帮助!
发布于 2013-03-04 12:27:28
问题是,虽然您可以在bison中定义和使用像"<<"
和">>"
这样的标记,但这些标记没有宏来扩展到它们在.tab.h文件中定义的值,因此没有(简单的)方法在词法分析器中生成这些标记。为了使用它们,您需要找出分配给它们的标记值(一个整数)(可以在.output文件中看到)并返回该整数。但对.y文件的任何更改(添加的任何新标记,甚至只是重新排序的内容)都可能会改变这一点,因此几乎不可能进行维护。
相反,定义名称标记(如LSHIFT
和RSHIFT
)更有意义,bison将为其生成扩展到标记编号的宏,从而允许您在词法分析器中轻松引用它们。
发布于 2013-03-04 20:43:40
我建议使用
%token LSHIFT "<<"
...
%left "<<"
...
expression: expression "<<" expression {...}
在Bison文件和Flex文件中:
"<<" return LSHIFT;
注意在语法文件中使用"<<"
,而不是在编写语法文件时使用'<<'
。
发布于 2013-03-04 14:58:28
你的Flex源不正确;文件末尾的%}
应该在文件的上方,但这太糟糕了,以至于把材料复制到这样的地方肯定是个问题(在问题中显示的%}
中,你得到了‘过早的EOF’)。
未升级测试工具以打印新条目。当我将else
子句更改为:
else
printf("%d\t\tUNKNOWN (%s)",ch, yytext);
然后在这组符号上运行测试程序,它看起来是这样的:
Lex Token
----------------------------
()+*=-~ &|^>>**<<;,()===
( L_PARENTHESIS
) R_PARENTHESIS
+ PLUS_OP
* MULT_OP
= ASSIGNMENT_STMT
- MINUS_OP
~ TILDE
279 UNKNOWN (&)
280 UNKNOWN (|)
281 UNKNOWN (^)
284 UNKNOWN (>>)
260 UNKNOWN (**)
283 UNKNOWN (<<)
; SEMICOLON
, COMMA
( L_PARENTHESIS
) R_PARENTHESIS
== EQ_OP
= ASSIGNMENT_STMT
0 UNKNOWN ()
在此之前,它将打印表面上为空白的行,尽管实际上它们上有控制字符,因为279-283被模数256简化为字符代码23-27或control-W以控制-[。
https://stackoverflow.com/questions/15193178
复制相似问题