我在yacc(Bison)中有一个简单的语法:

Expressions.y:

%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "../C_routines/SyntaxTree.h"

extern int yylineno;

int yylex();
void yyerror(const char *s);
int i=0;

typedef struct Exp {
    char *code;
    char *addr;
} Exp;
%}

%union {
    char *lexeme;
    char *value;
    double dvalue;
    struct SyntaxTree *Sy;
    int ivalue;
}

%type <Sy> E S
%token <lexeme> id ID 
%token <value> LITERAL
%token <dvalue> FLOAT
%token <ivalue> INT

%left '+' '-'
%left UMINUS

%%

S : id "=" E { $$ = newST('=',newid($1), $3); printSyntaxTree($$); }
  ;

E : E "+" E { $$ = newST('+', $1, $3); }
  | E "-" E { $$ = newST('-', $1, $3); }
  | "(" E ")" { $$ = $2; }
  | "-" E %prec UMINUS { $$ = newST(UMINUS, NULL, $2); }
  | id { $$ = newid($1); }
  | INT { $$ = newint($1); }
  | FLOAT { $$ = newdouble($1); }
  ;

%%

void yyerror(const char *s) {
    fprintf(stderr, "Parser error at %d: %s\n", yylineno, s);
}

int main() {
    yyparse();
    return 0;
}

莱克斯:

%option yylineno

%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "../yacc/expressions.tab.h"
#include "../C_routines/SymbolTable.h"

%}

id [a-zA-Z_][a-zA-Z_0-9]*

INT [-]?[0-9]+
FLOAT [-]?[0-9]+([.][0-9]+)?([Ee][+-]?[0-9]+)?
bool "True" | "False"
str (\"([^\"\\\\]|\\\\.)*\")|('([^'\\\\]|\\\\.)*')

assign [+-/%*]?=
arith [+-/%*]


%%

{id} {
    printf("\nIdentifier : %s ", yytext);
    int a = installID(yytext, "ID");
    yylval.lexeme = strdup(yytext);
    return id;
}

{INT} {printf("\nInteger : %s ",yytext);
      int a = installLit(yytext,"INT");
      yylval.value = strdup(yytext);
      return INT;}

{str} {printf("String ");
      int a = installLit(yytext,"STR");
      yylval.value = strdup(yytext);
      return LITERAL;}

{FLOAT} {printf("Float ");
      int a = installLit(yytext,"FLOAT");
      yylval.value = strdup(yytext);
      return FLOAT;}

{assign} {printf("Assignment Operator\n");}
{arith} {printf("Arithmetic Operator\n");}


%%

int yywrap(){
  return 1;
}

当我运行这些命令时:

输出1

a=0

Identifier : a Assignment Operator

Integer : 0 Parser error at 1: syntax error

输出2


a=b

Identifier : a Assignment Operator

Identifier : b Parser error at 1: syntax error

输出3

a=-4

Identifier : a Assignment Operator

Integer : -4 Parser error at 1: syntax error

输出4:不,不,不.

a=5+6

Identifier : a Assignment Operator

Integer : 5 Parser error at 1: syntax error

我已经为操作符和终结符定义了足够的优先级和结合性. 我不知道是什么导致了第1行的语法错误.好心帮忙.我使用flex作为lex,使用bison作为yacc

编辑:在申报部分增加#define YYERROR_VERBOSE 1给出,

输出1:

a=0

Identifier : a Assignment Operator

Integer : 0 Parser error at 1: syntax error, unexpected INT, expecting =

输出2:

a=a+b

Identifier : a Assignment Operator

Identifier : a Parser error at 1: syntax error, unexpected id, expecting =

输出3:

a = b

Identifier : a  Assignment Operator

Identifier : b Parser error at 1: syntax error, unexpected id, expecting =

我在我的输入中输入了=,但它再次要求=符号

推荐答案

野牛说,它没有收到预期的"=",它没有撒谎. 调查一下词法分析器.该规则打印"赋值运算符",从不返回任何内容.从解析器的Angular 来看,那里什么都没有.

由于这些原因,使用printf进行调试是不可靠的.您应该使用proper ways来调试您的词法分析器和解析器.

C++相关问答推荐

如何将匿名VLA分配给指针?

try 使用sigqueue函数将指向 struct 体的指针数据传递到信号处理程序,使用siginfo_t struct 体从一个进程传递到另一个进程

InetPton()函数无效的IP地址

在C中使用JMP_buf数组进行线程化(在xv6中测试)

为什么cudaFree不需要数据 struct 的地址?

为什么该函数不将参数值保存到数据 struct 中?

C-使用指针返回修改后的整数数组

为什么memcpy进入缓冲区和指向缓冲区的指针工作相同?

有什么方法可以将字符串与我们 Select 的子字符串分开吗?喜欢:SIN(LOG(10))

为什么双精度d=flt_max+flt_max;在c语言中得到inf的结果

变量的作用域是否在C中的循环未定义行为或实现定义行为的参数中初始化?

预处理器宏扩展(ISO/IEC 9899:1999(E)§;6.10.3.5示例3)

C整型和_泛型.哪些类型是兼容的?

使用正则表达式获取字符串中标记的开始和结束

C 和 C++ 标准如何告诉您如何处理它们未涵盖的情况?

#define X Defined(Y) 是有效的 C/C++ 宏定义吗?

10 个字节对于这个 C 程序返回后跳行的能力有什么意义

使用复合文字数组初始化的指针数组

无法在线程内用 C 打印?

strlen 可以是[[未排序]]吗?