【发布时间】:2021-05-14 08:17:19
【问题描述】:
我正在通过 lax 和 yacc 构建一个小型解释器,该解释器适用于执行加法和乘法以及打印整数列表的基本编程语言。
例如指令:
Print(2,3,4);
应该输出:2 3 4
和指令:
Print(+(2,3));
应该输出:5
第一条打印指令运行良好。然而,任何加法指令(+ 后跟一个列表)都会自行运行,并且该操作会返回正确的答案(通过 printf 找到)但似乎 yacc 在执行加法指令之后发生的外部打印指令之前停止。
这是我的 .l 文件:
%{
#include "y.tab.h"
%}
digit [0-9]
%%
{digit}{digit}* {yylval.str = strdup(yytext); return IntLit;}
Print {return Print;}
\+ {yylval.str = strdup(yytext); return '+';}
\* {yylval.str = strdup(yytext); return '*';}
\( {return '(';}
\) {return ')';}
\, {return ',';}
\; {return ';';}
\t {}
\r {}
\n {}
%%
int yywrap () {
return 1;
}
这是我的 .y 文件:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylex();
extern int yyparse();
extern int yyerror(char *s);
extern char *yytext;
void doPrint(char *s);
int evaluate(char *c, char *s);
char* append(char *s, char *s2);
char* makeSingle(char *s);
%}
%union {
char character;
char *str;
}
%type <str> Item
%type <str> IntLit
%type <str> List
%type <str> Func
%token Print
%token IntLit
%%
Prog : StmtSeq { };
StmtSeq : Stmt StmtSeq { };
StmtSeq : { };
Stmt : Print '(' List ')' ';' { doPrint($3); };
List : List ',' Item { $$ = append($1, $3); };
List : Item { $$ = makeSingle($1); };
Item : Func '(' List ')' { $$ = evaluate($1, $3); };
Item : IntLit { $$ = $1;};
Func : '+' {$$ = yylval.str; };
Func : '*' {$$ = yylval.str; };
%%
int main(int argc, char *argv[]){
//yydebug = 1;
return yyparse();
}
void doPrint(char *s){
char * token = strtok(s, ",");
while(token != NULL){
printf("%s", token);
printf(" ");
token = strtok(NULL, ",");
}
printf("\n");
}
int evaluate(char *c, char *s){
char * result;
int res;
int x;
char * token;
int cmp = strcmp(c, "+");
if(cmp == 0){
token = strtok(s, ",");
res = 0;
while(token != NULL){
x = atoi(token);
res = res + x;
token = strtok(NULL, ",");
}
sprintf(result,"%d",res);
} else {
token = strtok(s, ",");
res = 1;
while(token != NULL){
x = atoi(token);
res = res * x;
token = strtok(NULL, ",");
}
sprintf(result,"%d",res);
}
printf("resultstring is: '%s'\n", result);
return result;
}
char* append(char *s, char *s2){
char * result = s;
strcat(result, ",");
strcat(result, s2);
return result;
}
char* makeSingle(char *s){
//char * result;
//sprintf(result, "%d", c);
//return result;
return s;
}
extern int yyerror(char *s) {
printf(s);
return 1;
}
如果我输入指令:
Print(2,3,4);
Print(+(2,3));
第一条打印指令按预期工作,但第二条指令在打印加法结果之前停止,但在评估完成之后。
我是 yacc/lex 的新手,我不确定为什么 yacc 在不打印加法结果的情况下停止。添加的结果不应该是可以重写为“列表”然后正确打印的“项目”吗?任何帮助或建议将不胜感激,谢谢!
编辑
在查看yydebug = 1; 时的输出后,我发现解析在完全减少之前突然结束(我相信)。调试过程的最后一部分内容如下:
Reducing stack by rule 7 (line 40):
$1 = nterm Func ()
$2 = token '(' ()
$3 = nterm List ()
$4 = token ')' ()
在此缩减中没有$$,因为在之前完成的所有其他缩减中都存在
【问题讨论】: