Yacc和Lex在解析使用二元运算符的表达式时出错

时间:2013-05-15 18:24:52

标签: 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

%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();
}

这是Lex的.l文件:

%{
   #include "testYacc.h"
%}

number [0-9]+

%%
[ ]             { /* skip blanks */ }
{number}        { sscanf(yytext, "%d", &yylval); return NUMBER; }
home            { return HOME; }
pu              { return PU; }
pd              { return PD; }
fd              { return FD; }
bk              { return BK; }
rt              { return RT; }
lt              { return LT; }

%%

当我尝试在命令行上输入算术表达式以进行评估时,会导致以下错误:

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

1 个答案:

答案 0 :(得分:2)

你的词法分析器缺少匹配和返回标记的规则,例如'+''*',所以如果输入中有任何内容,它只会回显它们并丢弃它们。当您输入fd (10 + 10)时会发生这种情况 - 词法分析器返回标记FD NUMBER NUMBER,而+(会回显到标准输出。解析器然后给出语法错误。

您想要添加规则以返回这些单个字符标记。最简单的方法是在最后添加一个规则到.l文件中:

.               { return *yytext; }

匹配任何单个字符。

请注意,这与\n(换行符)不匹配,因此输入中的换行符仍会被回显和忽略。您可能希望将它们(以及制表符和回车符)添加到跳过空白规则:

[ \t\r\n]       { /* skip blanks */ }