我有一个Lex和YACC程序来生成一个开关解析器,它应该产生以下内容:
switch(var) {
case 0: z=cost0;
break;
case N: z=costN;
break;
default: z=costD;
break;
}
并且通过传递存储在变量x和y中的2个默认值(分别为1和2),它们中的每一个都将被传递给开关中的val,并且将检查所有N个条件,因此, z应该为找到的条件的值存储变量并打印它。但我不能写我的YACC的主要功能来组织x和y的输入,并打印z。 这是我的节目:
莱克斯:
%{
#include"ma1.tab.h"
%}
alpha [a-zA-Z]
digit [0-9]
%%
[ \t\n]
switch return SWITCH;
int return INT;
case return CASE;
break return BREAK;
default return DEFAULT;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
. return yytext[0];
%%
YACC:
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token ID NUM SWITCH CASE DEFAULT BREAK INT
%right '='
%%
program: varassign switchstm {printf("Input accepted.\n");exit(0);}
;
varassign: INT vardef ‘;’
;
vardef : ID '=' NUM | ID '=' NUM varassign {$1=$3;}
;
switchstm: SWITCH '(' ID ')' '{' block '}'
;
block: caselist
| caselist defaultstm
;
caselist: casestm | casestm caselist ;
casestm: CASE NUM ':' assign ';' BREAK ';'
;
defaultstm : DEFAULT ':' assign ';' BREAK ';'
;
assign : ID'='NUM {$1=$3}
%%
main()
{
printf("Enter the exp: ");
yyparse();
}
但是当我运行生成的a.out文件时,它什么也没做!所以我的问题是绕过代码以获得2个整数并让它们通过每个生成一个z。 提前谢谢。
答案 0 :(得分:1)
所以你所拥有的语法解析器与简单的编程语言(交换机语句加上一系列赋值)相匹配,但是它并没有做任何事情。所以它会运行并给你一个语法错误&#39;如果输入不符合语法,或者如果输入没有静默退出。
如果你想真正对程序做一些事情(评估它?将它转换成机器代码?字节码?),你需要在.y文件中添加动作来扫描令牌并产生有用的数据结构和/或输出。
您的第一步是处理NUM
和ID
令牌,因为这些令牌具有关联值。您需要在yacc代码中定义%union
以保存值:
%union {
int num;
char *id;
}
将令牌声明为使用这些类型:
%token<num> NUM
%token<id> ID
并让lex代码返回这些值:
{digit}+ { yylval.num = atoi(yytext); return NUM; }
{alpha}({alpha}|{digit})* { yylval.id = strdup(yytext); return ID; }
通过这种方式,您可以开始向yacc代码添加操作来执行操作。