Parsing 解析使用二进制运算符的表达式时出现Yacc和Lex错误
我不熟悉Lex和Yacc,我正在尝试为一种简单的语言创建一个解析器,它允许基本的算术和等式表达式。虽然我有一些工作,但在尝试解析包含二进制操作的表达式时遇到了错误。这是我的Parsing 解析使用二进制运算符的表达式时出现Yacc和Lex错误,parsing,yacc,lex,lexical-analysis,Parsing,Yacc,Lex,Lexical Analysis,我不熟悉Lex和Yacc,我正在尝试为一种简单的语言创建一个解析器,它允许基本的算术和等式表达式。虽然我有一些工作,但在尝试解析包含二进制操作的表达式时遇到了错误。这是我的.y文件: %{ #include <stdlib.h> #include <stdio.h> %} %token NUMBER %token HOME %token PU %token PD %token FD %token BK %token RT %token LT
.y
文件:
%{
#include <stdlib.h>
#include <stdio.h>
%}
%token NUMBER
%token HOME
%token PU
%token PD
%token FD
%token BK
%token RT
%token LT
%left '+' '-'
%left '=' '<' '>'
%nonassoc UMINUS
%%
S : statement S { printf("S -> stmt S\n"); }
| { printf("S -> \n"); }
;
statement : HOME { printf("stmt -> HOME\n"); }
| PD { printf("stmt -> PD\n"); }
| PU { printf("stmt -> PU\n"); }
| FD expression { printf("stmt -> FD expr\n"); }
| BK expression { printf("stmt -> BK expr\n"); }
| RT expression { printf("stmt -> RT expr\n"); }
| LT expression { printf("stmt -> LT expr\n"); }
;
expression : expression '+' expression { printf("expr -> expr + expr\n"); }
| expression '-' expression { printf("expr -> expr - expr\n"); }
| expression '>' expression { printf("expr -> expr > expr\n"); }
| expression '<' expression { printf("expr -> expr < expr\n"); }
| expression '=' expression { printf("expr -> expr = expr\n"); }
| '(' expression ')' { printf("expr -> (expr)\n"); }
| '-' expression %prec UMINUS { printf("expr -> -expr\n"); }
| NUMBER { printf("expr -> number\n"); }
;
%%
int yyerror(char *s)
{
fprintf (stderr, "%s\n", s);
return 0;
}
int main()
{
yyparse();
}
尝试在命令行上输入算术表达式进行求值时,会导致以下错误:
home
stmt -> HOME
pu
stmt -> PU
fd 10
expr -> number
fd 10
stmt -> FD expr
expr -> number
fd (10 + 10)
stmt -> FD expr
(expr -> number
+stmt -> FD expr
S ->
S -> stmt S
S -> stmt S
S -> stmt S
S -> stmt S
S -> stmt S
syntax error
您的lexer缺少匹配和返回标记的规则,例如
'+'
和'*'
,因此如果您的输入中有任何标记,它将只回显并丢弃它们。这就是当您输入fd(10+10)
时所发生的情况——lexer返回标记fd
NUMBER
NUMBER
,而+
和(
返回到stdout。然后解析器给出一个语法错误
您希望添加一条规则以返回这些单字符标记。最简单的方法是在结尾处向.l文件添加一条规则:
. { return *yytext; }
它匹配任何单个字符
请注意,这与\n
(换行符)不匹配,因此输入中的换行符仍将被回显和忽略。您可能希望将它们(以及制表符和回车符)添加到跳过空格规则中:
[ \t\r\n] { /* skip blanks */ }
谢谢,我想知道这一点。我想出于某种原因,因为引用了+
等,它们在yacc中是某种特殊的“基本”运算符。它们是,在yacc中。这就是为什么只返回char值有效,而不必为它们定义%标记。但它们在lex/flex中并不特殊。我明白了,为了让它们正确地说,它们首先需要在Lex中定义为标记bk 10
将首先显示expression->number
,并且似乎没有捕捉到bk
。但是,再次输入它,它将正确解析,即语句->bk expr
,然后是expression->number
。延迟的原因是什么?@Dylan:那是因为你的printf在e动作,当规则减少时发生——当规则的rhs上的所有符号都被解析,并且它们被组合成lhs上的单个符号时。解析从标记到符号,但是使用规则的->
会让你陷入相反的思考方向。
[ \t\r\n] { /* skip blanks */ }