【问题标题】:Yacc and Lex "syntax error"Yacc 和 Lex “语法错误”
【发布时间】:2023-03-19 14:11:02
【问题描述】:

当我试图检查表达式“boolean 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);}

【问题讨论】:

  • 拼写:是“bool”还是“boolean”?
  • 对不起。我正在尝试检查表达式“boolean x;”
  • 请格式化这个难以辨认的混乱。
  • 首先修复由 yacc/bison 产生的所有警告。最相关的是“错误:使用了符号 boolST,但未定义为令牌并且没有规则”。 (如果你仔细观察,规则boolSt: BOOL 并没有定义符号boolST。)我不清楚为什么你觉得你需要一个非终端。你可以写boolExp: BOOL id。或者,如果您使用过%token BOOL "boolean",您可以使用更具可读性的boolExp: "boolean" id
  • @sophievi:字符类将匹配字符列表中的字符。 [\n\t ] 将匹配换行符、制表符或空格。 [ \n\t] 也是如此。但[\n\t] 只匹配换行符或制表符。您的问题具有正确的字符类,但由于 sepp2k 指出的原因而失败。您在任何地方都没有表明您删除了字符类中的空格。

标签: parsing ubuntu compiler-construction yacc lex


【解决方案1】:

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

所以让我们在打印匹配字符的词法分析器中的. 规则中添加一条打印语句,这样我们就可以看到它在哪里产生了意外字符。现在我们看到它打印了一个空格,但是空格应该被忽略了,对吧?所以让我们看看应该这样做的规则:

[\n\t ]+;

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

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

【讨论】:

  • 感谢您的回答。但它没有用。我删除了分号,我得到了相同的语法错误。当我尝试添加 %error-verbose 时,当我输入“yacc project1.y”时,我得到“yacc: e-line 14 of "project1.y”,语法错误 %error-verbose"
  • 我尝试为 lex 文件中的每个标记制作 printf。对于 "x=3" 它打印 id=num;对于“布尔 x;”它打印语法错误布尔值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多