Bison 带yacc的多字符算子

Bison 带yacc的多字符算子,bison,yacc,lex,flex-lexer,Bison,Yacc,Lex,Flex Lexer,我一直在尝试向给定的前缀/中缀/后缀计算器添加位运算符,但由于某些原因,我无法使用yacc识别运算符“**”。我到处找过一些有类似问题的人,特别是这个问题,但没有找到有效的解决方案 我的莱克斯档案 %{ #include "zcalc.h" #include <math.h> int ch; int flag = 0; #define NAME 257 #define SEMISYM 268 #define COMMASYM 269 #define L

我一直在尝试向给定的前缀/中缀/后缀计算器添加位运算符,但由于某些原因,我无法使用yacc识别运算符“**”。我到处找过一些有类似问题的人,特别是这个问题,但没有找到有效的解决方案

我的莱克斯档案

%{
#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;
    }

    %}
%{
#包括“zcalc.h”
#包括
int-ch;
int标志=0;
#定义名称257
#定义SEMISYM 268
#定义COMMASYM 269
#定义LPARSYM 270
#定义RPARSYM 271
#定义等式SYM 272
#定义PLUSSYM 273
#定义MULTSYM 274
#定义ASGNSYM 275
#定义最小SYM 276
#定义数字277
#定义TILDE 278
/*我加的新东西*/
#定义比特和279
#定义比特数280
#定义位异或281
/*#定义BITNOT 282*/
#定义LSHIFT 283
#定义重新换档284
#定义电源285
无效yyerror(char*mesg);/*yacc错误检查器*/
/*lex分析器的定义*/
字母[A-Za-z]
数字[0-9]+
ident{letter}({letter}{digit})*
ws[\t\n]+
其他的。
%%
{ws};/*----令牌和操作--*/
/*新东西*/
“&”返回位和;
“|”返回位;
“^”返回位异或;
“”返回重新换档;
“**”返回功率;
"//".* ;                
“;”返回半符号;
“,”返回通信系统;
“(“返回LPARSYM;
“)返回RPARSYM;
“==”返回等式SYM;
“+”返回PLUSSYM;
“*”返回MULTSYM;
“=”返回ASGNSYM;
“-”返回MINUSSYM;
“~”返回TILDE;
/*新东西
“&”返回位和;
“|”返回位;
“^”返回位异或;
“”返回重新换档;
“**”返回功率*/
{ident}{
返回名称;
}
{数字}{
返回号码;
}
“$”{返回0;}
{other};/*忽略其他内容*/
%%
无效yyerror(char*mesg);/*yacc错误检查器*/
/*yacc误差函数*/
无效错误(字符*mesg){
flag=1;
printf(“%s\n”,mesg);
}
int main(){
printf(“Lex\t\tToken\t\t\n”);/*列标题*/
printf(“-----------------------------\n”);
做
{
ch=yylex();
if(ch==SEMISYM)
printf(“%s\t\tSEMICOLON”,yytext);
else if(ch==COMMASYM)
printf(“%s\t\t命令”,yytext);
else if(ch==LPARSYM)
printf(“%s\t\tL_括号”,yytext);
else if(ch==RPARSYM)
printf(“%s\t\tR_括号”,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\t结果”,yytext);
else if(ch==ASGNSYM)
printf(“%s\t\t签名”,yytext);
else if(ch==MINUSSYM)
printf(“%s\t\tMINUS_OP”,yytext);
else if(ch==编号)
printf(“%s\t\t编号”,yytext);
else if(ch==名称)
printf(“%s\t\t名称\t\t”,yytext);
else if(ch==TILDE)
printf(“%s\t\tTILDE\t\t”,yytext);
其他的
printf(“%c”,ch);
printf(“\n”);/*结束检查令牌读取*/
}
while(ch!=0);/*一直读到文件结尾*/
返回0;
}
int yywrap(){
返回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;
}
%{
#包括“zcalc.h”
#包括
#包括
#包括
#包括
int标志=0;
无效yyerror(char*mesg);/*yacc错误检查器*/
%}
%联合{
双dval;
结构符号表*符号;
}
%令牌名
%令牌号
//%LSHIFT令牌
//%r标记移位
%代币权
%左''''+'
//%左“**”
%左'*''/'
//%左L档重新换档
//%左幂
%类型表达式
%%
语句列表:语句'\n'
|语句\u列表语句'\n'
语句:名称“=”表达式{$1->value=$3;}
|表达式{printf(=%g\n“,$1);}
表达式:“+”表达式{$$=$2+$3;}
|“-”表达式{$$=$2-$3;}
|幂表达式{$$=$3;}
|“*”表达式{$$=$2*$3;}
|“/”表达式{$$=$2/$3;}
|“&”表达式{$$=(int)$2&(int)$3;}
|“|”表达式{$$=(int)$2 |(int)$3;}
|“^”表达式{$$=(int)$2^(int)$3;}
|“”表达式{$$=(int)$3>>(int)$4;}
//|“**”表达式{$$=pow($2,$3);}
|“~”表达式{$$=~(int)$2;}
|“(“表达式”)”{$$=$2;}
|数
|名称{$$=$1->value;}
%%
结构symtab*symlook(字符*s){
char*p;
结构符号表*sp;
对于(sp=symtab;sp<&symtab[NSYMS];sp++){
/*已经到了吗*/
如果(sp->name&&!strcmp(sp->name,s))
返回sp;
/*是免费的吗*/
如果(!sp->name){
sp->name=strdup;
返回sp;
}
/*否则继续下一步*/
}
yyerror(“符号太多…\n”);
出口(1);
}
void addfunc(字符*名称,双(*func)(){
结构symtab*sp=symlook(名称);
sp->funcptr=func;
}
/*yacc误差函数*/
无效错误(字符*mesg){
flag=1;
printf(“%s\n”,mesg);
}
int main(){
yyparse();
返回0;
}

我在标题中摆弄了定义和规则的位置,但这似乎不起作用。我可以使用“使“”工作。问题是,尽管您可以在bison中定义和使用类似于“
”>“
的令牌,但此类令牌没有扩展到.tab.h文件中定义的值的宏,因此没有(简单的)方法在lexer中生成令牌。为了使用它们,您需要找出bison分配给它们的令牌值(一个整数)(可以在.output文件中看到)并返回该整数。但是对.y文件的任何更改(添加的任何新标记,甚至只是重新排序的东西)都可能会改变这一点,因此几乎不可能进行维护

相反,定义bison将为其生成ma的名称标记(如
LSHIFT
RSHIFT
)更有意义
    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 ()
%token LSHIFT "<<"
...
%left "<<"
...
expression: expression "<<" expression {...}
"<<"  return LSHIFT;