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|\r\n)
whitespace [\t \n\r]*
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 "/*"[.\r\n]*"*/"
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. = %s\n",
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("interface\n"); }
| CLASS Class SCOL { printf("class\n");}
| error { printf("error on: %s\n", $$); }
;
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: %s\n", $$); }
;
Num : HEX
| INT
;
Exprs : Expr COMMA Exprs
| Expr
;
%%
void yyerror(char *s) {
fprintf(stderr, "Parse Error on line %i: %s\n", line_number, s);
}
int main(void){
yyparse();
}
前两个输入按预期识别,
但是,第三个因错误error on: y
而失败,我不知道为什么。
在我看来,这应该是 aClass
和 a Member
METHOD
,其中包含一个Stat
(ement)RETURN
和Expr
Term
a ID
。
我尝试评论并删除所有不必要的位,但结果仍然相同。我还查看了解析器以验证我的标识符是否正确解析,但我认为它们应该正确解析。
为什么这里的y
inreturn y
不被识别?我不知道的语法是否存在冲突?
(请注意,我并不指望您修复完整的语法;我只是询问这不起作用的原因。我确信那里还有其他错误,但我真的坚持修复这个错误。)
这也是我的makefile:
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;
所以 ';' afterreturn y
必须移到第一个之后end
(而且return x
似乎更合乎逻辑,但这是另一个主题,您不检查ID的有效性)
其中一个类只能有一个成员,这是非常有限/限制性的
推荐阅读
- swift - 如何将文本字段限制为仅输入 Double 值
- css - Flexbox:当列的宽度不同时,可以对齐第一行=底部和第二行=顶部吗?
- javascript - 如何通过将数组传递给函数来删除数组中的空对象 - javascript?
- regex - 正则表达式:dd/mm/yyyy 不包括某些年份
- mapreduce - Grunt - Mapreduce 模式:重试连接到服务器:0.0.0.0/0.0.0.0:10020。已尝试 8 次;重试策略为 RetryUpToMaximum
- php - 如何在特定时间刷新页面
- mongodb - MongoDB - mongodb 设置向导提前结束
- flutter - Flutter:如何使用两个嵌套的导航器弹出?
- wordpress - 将 URL 参数拉入 WordPress“原始 HTML”内容元素
- python - 从python脚本调用jenkins post api时出现403禁止错误