1

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

这是我.l的 Lex 文件:

%{
   #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
4

1 回答 1

2

您的词法分析器缺少匹配和返回诸如'+'and之类的标记的规则'*',因此如果您的输入中有任何标记,它只会回显它们并丢弃它们。这就是您输入时发生fd (10 + 10)的情况——词法分析器在返回标记FD NUMBER NUMBER时返回+(回显到标准输出。然后解析器给出一个语法错误。

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

.               { return *yytext; }

匹配任何单个字符。

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

[ \t\r\n]       { /* skip blanks */ }
于 2013-05-15T21:56:50.293 回答