c语言 - 为什么此语法不解析 return 语句?



我正在尝试编写一种可以解析以下 3 个输入的语法

-- testfile --
class hi implements ho:
var x:int;
end;
-- testfile2 --
interface xs:
myFunc(int,int):int
end;
-- testfile3 --
class hi implements ho:
method myMethod(x:int)
return y;
end
end;

这是lexer.l

%{
#include <stdio.h>
#include <stdlib.h>
#include "parser.tab.h"
#include <string.h>
int line_number = 0;
void lexerror(char *message);
%}
newline         (n|rn)
whitespace      [t nr]*
digit           [0-9]
alphaChar       [a-zA-Z]
alphaNumChar    ({digit}|{alphaChar})
hexDigit        ({digit}|[A-Fa-f])
decNum          {digit}+
hexNum          {digit}{hexDigit}*H
identifier      {alphaChar}{alphaNumChar}*
number          ({hexNum}|{decNum})
comment         "/*"[.rn]*"*/"
anything        .
%s InComment
%option noyywrap
%%
<INITIAL>{
interface       return INTERFACE;
end             return END;
class           return CLASS;
implements      return IMPLEMENTS;
var             return VAR;
method          return METHOD;
int             return INT;
return          return RETURN;
if              return IF;
then            return THEN;
else            return ELSE;
while           return WHILE;
do              return DO;
not             return NOT;
and             return AND;
new             return NEW;
this            return THIS;
null            return _NULL;
":"             return COL;
";"             return SCOL;
"("             return BRACL;
")"             return BRACR;
"."             return DOT;
","             return COMMA;
"="             return ASSIGNMENT;
"+"             return PLUS;
"-"             return MINUS;
"*"             return ASTERISK;
"<"             return LT;

{decNum}        {
yylval = atoi(yytext);
return DEC; 
}
{hexNum}        {
const int len = strlen(yytext)-1;
char* substr = (char*) malloc(sizeof(char) * len);
strncpy(substr,yytext,len);
yylval = (int)strtol
( substr
, NULL
, 16);
free (substr);
return HEX;
}
{identifier}    {
yylval= (char *) malloc(sizeof(char)*strlen(yytext));
strcpy(yylval, yytext);
return ID; 
}
{whitespace}    {}
"/*"        BEGIN InComment;
}
{newline}       line_number++;
<InComment>{
"*/"            BEGIN INITIAL;
{anything}      {}
}
.               lexerror("Illegal input");
%%
void lexerror(char *message)
{
fprintf(stderr,"Error: "%s" in line %d. = %sn",
message,line_number,yytext);
exit(1);
}

这是parser.y

%{
# include <stdio.h>
int yylex(void);
void yyerror(char *);
extern int line_number;
%}
%start Program
%token INTERFACE END CLASS IMPLEMENTS VAR METHOD INT RETURN IF THEN ELSE
%token WHILE DO NOT AND NEW THIS _NULL EOC SCOL COL BRACL BRACR DOT COMMA 
%token ASSIGNMENT PLUS ASTERISK MINUS LT EQ DEC HEX ID NEWLINE

%% 
Program: INTERFACE Interface SCOL      { printf("interfacen"); }
| CLASS Class SCOL          { printf("classn");} 
| error { printf("error on: %sn", $$); }
;  

Interface: ID COL 
AbstractMethod  
END
;  

AbstractMethod: ID BRACL Types BRACR COL Type
;
Types : Type COMMA Types
| Type 
;
Class: ID 
IMPLEMENTS ID COL
Member SCOL 
END  
;  

Member: VAR ID COL Type  
| METHOD ID BRACL Pars BRACR Stats END
;  

Type: INT  
| ID 
;  

Pars: Par COMMA Pars
| Par
;  

Par: ID COL Type 
;  

Stats: Stat SCOL Stat
| Stat
;  

Stat: RETURN Expr  
| IF Expr THEN Stats MaybeElse END  
| WHILE Expr DO Stats END  
| VAR ID COL Type COL ASSIGNMENT Expr
| ID COL ASSIGNMENT Expr 
| Expr        
;  
MaybeElse : 
| ELSE Stats
;
Expr: NOT Term  
| NEW ID 
| Term PLUS Term 
| Term ASTERISK Term
| Term AND Term
| Term ArithOp Term  
| Term
;  
ArithOp: MINUS
| LT
| ASSIGNMENT
;
Term: BRACL Expr BRACR
| Num
| THIS  
| ID 
| Term DOT ID BRACL Exprs BRACR
| error { printf("error in term: %sn", $$); }
;
Num : HEX
| INT
;
Exprs : Expr COMMA Exprs
| Expr
;
%%
void yyerror(char *s) {
fprintf(stderr, "Parse Error on line %i: %sn", line_number, s);
}
int main(void){
yyparse();
}

前两个输入按预期识别,

但是,第三个失败并出现错误error on: y,我不知道为什么。

在我看来,这应该是一个Class,其MemberMETHOD包含一个Stat(ement)RETURNExprTerm是一个ID

我尝试评论并删除所有不必要的位,但结果仍然相同。 我还查看了解析器以验证我的标识符是否正确解析,但在我看来,它们应该解析。

为什么这里不承认return yy? 我不知道语法中是否存在冲突?

(请注意,我不希望您修复完整的语法;我只是在问这不起作用的原因。我确定那里还有其他错误,但我真的无法修复这个错误。

这也是我的制作文件:

CC    = gcc
LEX   = flex 
YAC   = bison
scanner: parser.y lexer.l
$(YAC) -d -Wcounterexamples parser.y
$(LEX) lexer.l
$(CC)  parser.tab.c parser.tab.h lex.yy.c -o parser
clean:
rm -f *.tab.h *.tab.c *.gch *.yy.c
rm ./parser

测试:

cat testfile3 | ./parser

首先,你的语法中有一个错误:

Stats: Stat SCOL Stat
| Stat
;  

必须是

Stats: Stat SCOL Stats
| Stat
;  

(行尾添加"s")

其次,您在testfile3中的定义不遵循您的语法,并且必须

class hi implements ho:
method myMethod(x:int)
return y
end;
end;

所以return y后面的';"必须在第一个end之后移动

(return x似乎更合乎逻辑,但这是另一个主题,您不检查ID的有效性)


其中,一个类只能有一个成员,这是非常有限/限制性的

相关内容

最新更新