Parsing Yacc和Lex“;语法错误“;

Parsing Yacc和Lex“;语法错误“;,parsing,ubuntu,compiler-construction,yacc,lex,Parsing,Ubuntu,Compiler Construction,Yacc,Lex,当我试图检查表达式“布尔x”时,我得到了“语法错误”,我不明白为什么。 当我检查表达式“x=3;”或“2=1;”时,将生成抽象语法树,并且不会显示任何错误。 (在这个项目中,除了Lex和Yacc之外,我不允许使用任何东西,我使用的是Ubuntu) Lex文件: %% [\n\t ]+; boolean {return BOOL;} TRUE {return TRUE;} FALSE {return FALSE;} [0-9]+ {return NUM;} [a-zA-Z][0-9a-zA-Z]

当我试图检查表达式“布尔x”时,我得到了“语法错误”,我不明白为什么。 当我检查表达式“x=3;”或“2=1;”时,将生成抽象语法树,并且不会显示任何错误。 (在这个项目中,除了Lex和Yacc之外,我不允许使用任何东西,我使用的是Ubuntu)

Lex文件:

%%
[\n\t ]+; 
boolean {return BOOL;}
TRUE {return TRUE;}
FALSE {return FALSE;}
[0-9]+ {return NUM;}
[a-zA-Z][0-9a-zA-Z]* {return ID;}
. {return yytext[0];}
%%
Yacc文件:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node{
    struct node *left;
    struct node *right;
    char *token;
    } node;
node *mknode(node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%start code
%token ID,NUM,TRUE,FALSE,BOOL
%right '='
%%

code:lines{printtree($1); printf("\n");}
lines:calcExp';'|assignExp';'|boolExp ';'{$$ = $1;}
boolExp: boolST id{$$=$2;} 
calcExp: number '+' number {$$ = mknode($1,$3,"+");}
assignExp: id '=' number{$$ = mknode($1,$3,"=");}
boolSt : BOOL;
id : ID {$$ = mknode(0,0,yytext);}
number : NUM{$$ = mknode(0,0,yytext);}

%%
#include "lex.yy.c"
int main (void) {return yyparse();}

node *mknode(node *left, node *right, char *token){
    node *newnode = (node *)malloc(sizeof(node));
    char *newstr = (char *)malloc(strlen(token)+1);
    strcpy(newstr, token);
    newnode->left = left;
    newnode->right = right;
    newnode->token = newstr;
    return newnode;
 }

void printtree(node *tree){
    if (tree->left || tree->right)
        printf("(");
    printf(" %s ", tree->token);
    if(tree->left)
        printtree(tree->left);
    if(tree->right)
        printtree(tree->right);
    if(tree->left || tree->right)
        printf(")");
}
void yyerror (char *s) {
    fprintf (stderr, "%s\n",s);}
%{
#包括
#包括
#包括
类型定义结构节点{
结构节点*左;
结构节点*右;
字符*令牌;
}节点;
node*mknode(node*left,node*right,char*token);
无效打印树(节点*树);
#定义YYSTYPE结构节点*
%}
%起始代码
%令牌ID,NUM,TRUE,FALSE,BOOL
%对“=”
%%
代码:行{printtree($1);printf(“\n”);}
行:calcExp';'|赋值exp';'|boolExp';'{$$ = $1;}
boolExp:boolST id{$$=$2;}
calcExp:number'+'number{$$=mknode($1,$3,“+”);}
assignExp:id'='编号{$$=mknode($1,$3,“=”);}
boolSt:BOOL;
id:id{$$=mknode(0,0,yytext);}
编号:NUM{$$=mknode(0,0,yytext);}
%%
#包括“lex.yy.c”
int main(void){return yyparse();}
node*mknode(node*left,node*right,char*token){
node*newnode=(node*)malloc(sizeof(node));
char*newstr=(char*)malloc(strlen(令牌)+1);
strcpy(newstr,token);
新建节点->左=左;
新建节点->右=右;
newnode->token=newstr;
返回newnode;
}
无效打印树(节点*树){
如果(树->左|树->右)
printf(“(”);
printf(“%s”,树->令牌);
如果(树->左)
打印树(树->左);
如果(树->右)
打印树(树->右);
如果(树->左|树->右)
printf(“)”;
}
无效错误(字符*s){
fprintf(stderr,“%s\n”,s);}

调试语法错误的第一步是在bison文件中启用
%error verbose
。现在,它不再只是说“语法错误”,而是告诉我们,当需要标识符时,
boolean
关键字后面有一个意外字符

因此,让我们向lexer中打印匹配字符的
规则添加一条print语句,这样我们就可以看到它在哪里生成意外字符。现在我们看到它打印了一个空格,但是空格应该被忽略,对吗?让我们看看应该这样做的规则:

[\n\t ]+;
如果您的编辑器对flex文件有正确的语法高亮显示,那么问题现在应该很明显了:
被视为规则的一部分,而不是操作的一部分。也就是说,规则匹配空格,后跟分号,而不仅仅是匹配空格


因此,删除分号,它应该可以工作。

拼写:是“bool”还是“boolean”?哦,对不起。我正在检查表达式“布尔x;”请格式化这个难以辨认的混乱。首先修复yacc/bison产生的所有警告。最相关的一个是“错误:使用了符号boolST,但没有定义为令牌,也没有规则”。(如果仔细观察,规则
boolSt:BOOL
没有定义符号
boolSt
)我不清楚为什么您觉得这里需要一个非终端;您可以编写
boolExp:BOOL id
。或者,如果您使用了
%token BOOL“boolean”
,您可以使用更可读的
boolExp:“boolean”id
@sophievi:character类将匹配字符列表中的字符<代码>[\n\t]
将匹配换行符、制表符或空格。
[\n\t]
也是如此。但是
[\n\t]
只匹配换行符或制表符。您的问题具有正确的字符类,但由于sepp2k指出的原因而失败。没有任何地方表明您删除了字符类中的空格。谢谢您的回答。但它不起作用。我删除了分号,得到了同样的语法错误。当我试图添加%error verbose时,当我键入“yacc project1.y”时,我得到“yacc:e-line 14 of“project1.y”,语法错误%error verbose时,我试图为lex文件中的每个令牌生成printf。对于“x=3”,其打印id=num;对于“booleanx”,它打印了语法错误bool。