我对Flex和野牛很陌生,我正在做一个比较数字的应用程序。
如果a> b,它将返回0,而a 但是,当涉及到&,|,==时,我遇到了问题
这是我的输出示例:

>> a = 5

5

>> b = 8

8

>> a < b & a < b

1

>> syntax error


我不知道该如何解决这个问题。这是编译器的一些抱怨:

[tpham14@linux5 ~/331] make -f mymake calc
bison -d -o y.tab.c -v calc.y
calc.y: warning: 16 shift/reduce conflicts [-Wconflicts-sr]
calc.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr]
cc    -c -o y.tab.o y.tab.c
cc    -c -o lex.yy.o lex.yy.c
cc -o calc y.tab.o lex.yy.o


这是我的calc.y文件:

%{
#include "calc.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

/************************************************************************
* Defines a yacc grammar for a simple calculator using infix
* notation.  WHen executed, the calculator enters a loop in
* which it prints the prompt >>, reads a toplevel expression
* terminated by a newline, and prints its value.  Operators
* include +, -, *, and = (assignment). Note that all
* expressions return values, even assignment.  Parentheses
* can be used to override operator precedence and
* associativity rules. Based on zcalc by [email protected]
************************************************************************/
int yylex();
int yyparse();

%}

/*
  Th union directive specifies the collection of tpes our grammar
  deals with -- just doubles and pointers to symbol table entries.
*/

%union {
  double dval;
  struct symtab *symp;
  }

/*
  Declare the token types and any associated value types.  We made
  EQ a token in calc.l because otherwise '=' and '==' would clash.
*/
%token <symp> NAME
%token <dval> NUMBER
%token EQ
%token GT
%token LT
%token OR
%token AND
%token NOT
%token IF
%token ELSE
/* The folowing declarations specify the precidence and associativity
   of our operators. The operators -, +, * and / to be left
   associative, * and EQ to be right associative and UMINUS to be
   non-associative (since it is a unary operator). The '=' operator
   has the lowest precedence and UMINUS the highest.
*/

%right '='      /*lowest precedence*/
%right EQ GT LT
%left '-' '+'
%left '*' '/'
%left '&'
%nonassoc OR AND NOT
%nonassoc IF
%nonassoc ELSE
%nonassoc UMINUS     /* highest precedence */


/*
  Declare the type of expression to be a dval (double).
*/

%type <dval> expr
%type <dval> smallexprs
%%

/*
  Here are our grammar rules.  a session is a sequence of lines.  A
  toplevel is just an expr (print its value followed by two
  newlines and the prompt >>) or a '? (print help) or a '.' (exit).
  An expr can be a number, name, the sum of two exprs, ...
 */

session: /* empty */
         |session toplevel '\n'

;

toplevel:  expr                 { printf("%g\n\n>> ", $1); }
          | /*empty*/

                       | '?'                 { printHelp(); printf("\n>> "); }
          | '.'                 { printf("Exiting 331 calc\n"); exit(1); }


expr:   smallexprs                              { $$ = $1; }
       | NAME                                   { $$ = $1->value; }
       | NAME '=' expr                          { $1->value = $3; $$ = $3; }
       | IF   expr expr expr                    { if($2 == 1) $$ = $3; else $$ = $4; }
       | smallexprs AND smallexprs              { $$ = $1 && $3; }
       | smallexprs OR smallexprs               { $$ = $1 || $3; }
       | smallexprs EQ smallexprs               { $$ = $1 == $3; }
       | expr GT expr                           { $$ = $1 > $3; }
       | expr LT expr                           { $$ = $1 < $3; }
       | expr '+' expr                          { $$ = $1 + $3; }
       | expr '-' expr                          { $$ = $1 - $3; }
       | expr '*' expr                          { $$ = $1 * $3; }
       | expr '/' expr                          { $$ = $1 / $3; }

smallexprs: NUMBER                                      { $$ = $1; }
       | IF   smallexprs smallexprs smallexprs          { if($2 == 1) $$ = $3; else $$ = $4; }
       | smallexprs EQ smallexprs                       { $$ = $1 == $3; }
       | smallexprs GT smallexprs                       { $$ = $1 > $3; }
       | smallexprs LT smallexprs                       { $$ = $1 < $3; }
       | smallexprs '+' smallexprs                      { $$ = $1 + $3; }
       | smallexprs '-' smallexprs                      { $$ = $1 - $3; }
       | smallexprs '*' smallexprs                      { $$ = $1 * $3; }
       | smallexprs '/' smallexprs                      { $$ = $1 / $3; }
       | '~'  smallexprs %prec UMINUS                   { $$ = -$2; }
       | '('  smallexprs  ')'                           { $$ = $2; }


%%

struct   symtab *
symlook(s)
char *s;
{
   char *p;
   struct symtab *sp;

   /*  given the name of a symbol, scan the symbol table and
      either return the entry with matching name or add it
      to the next free cell in the symbol table. */

   for(sp = symtab; sp < &symtab[SYMBOLTABLESIZE]; sp++) {

     /* If the symbol table entry has a name and its equal
to the one we are looking for, return this entry */
     if (sp->name && !strcmp(sp->name, s))
       return sp;

         /* If the name is empty then this entry is free, so the
            symbol must not be in the table and we can add it here
            and return this entry. */
         if (!sp->name) {
           sp->name = strdup(s);
           return sp;
           }
       }

       /* We searched the entire symbol table and neither found
          the symbol or an unused entry.  So the table must be
          full.  Sigh. */
       yyerror("The symbol table is full, sorry...\n");
       exit(1);
    }



    void printHelp()
    { /* print calculator help and return */
      printf("Enter an expression in infix notation followed by a newline.\n");
      printf("Operators include +, -, * and =.  Defined functions include\n");
      printf("sqrt, exp and log.  You can assign a variable using the =\n");
      printf("operator. Type . to exit.  Syntax errors will terminate the\n");
      printf("program, so be careful.\n");
    }


    /* If error prints error and Do not accept to signify bad syntax in
       program */

    void yyerror(char *msg) /* yacc error function */
    {
      printf("%s \n" , msg);
    }

    int yywrap(){return 1;}

    int main()
    { /* print herald and call parser */
      printf("331 Calculator\n(type ? for help and . to exit)\n\n>> ");
      yyparse();
      return 0;
    }


以下是我的calc.l文件:

%{
#include "y.tab.h"
#include "calc.h"
#include <math.h>

/************************************************************************
A lexical scanner to recognize numbers, symbols and the EQ
operator.  When a NUMBER is found, its value is set is set to the
appropriate float.  When a NAME is found, an entry in symbol table is
created (with initial value 0.0) and the token's value is a pointer to
this entry.  If a '==' sequence is seen, it is returned as a token
EQ.  Spaces and tabs are ignored. Any other characters, including
a newline, are passed on as their own tokens. Based on the zcalc
calculator by [email protected]
************************************************************************/

%}

D     [0-9]
A     [a-zA-Z]
AD    [a-zA-Z0-9]

%%

({D}+|({D}*\.{D}+)([eE][-+]?{D}+)?) {yylval.dval = atof(yytext); return NUMBER;}

if                                 {return IF;}
or                                 {return OR;}
and                                {return AND;}
not                                {return NOT;}



{A}{AD}*                             {struct symtab *sp = symlook(yytext); yylval.symp = sp; return NAME;}

"=="                                 {return EQ;}
">"                                  {return GT;}
"<"                                  {return LT;}
[ \t]  ;

\n    |
.     return yytext[0];

%%


以下是我的calc.h文件:

#define SYMBOLTABLESIZE 30

/* An entry in the symbol table has a name, a pointer to a function,
   and a numeric value. */

struct symtab {
  char *name;
  double (*funcptr)();
  double value;
} symtab[SYMBOLTABLESIZE];

struct symtab *symlook();

void printHelp();
void yyerror();

最佳答案

语法错误,没有规则匹配或包含&

在lex规范中将&&令牌定义为“和”,您应使用

 a < b and a < b


或将lex规范更改为

  &&     { return AND;}
  ||     { return OR;}
  !      { return NOT;}


GT移位后,按smallexprs的方式减少Px,跟随包含GT
对于LT,+,-,*同样。 (6个移位/减少冲突)

 expr:   smallexprs                  --- Px
 smallexprs: smallexprs .GT smallexprs  ---Sy



expr: smallexprs EQ smallexprs .
smallexprs: smallexprs EQ smallexprs .


减少/减少遵循Expr和smallexprs产生的冲突(6减少/减少冲突)

关于c - Flex和Bison逻辑运算符语法错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58780417/

10-09 17:34