Lex程序换一个开关

时间:2017-02-02 10:22:56

标签: parsing switch-statement yacc lex

我有一个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。 提前谢谢。

1 个答案:

答案 0 :(得分:1)

所以你所拥有的语法解析器与简单的编程语言(交换机语句加上一系列赋值)相匹配,但是它并没有做任何事情。所以它会运行并给你一个语法错误&#39;如果输入不符合语法,或者如果输入没有静默退出。

如果你想真正对程序做一些事情(评估它?将它转换成机器代码?字节码?),你需要在.y文件中添加动作来扫描令牌并产生有用的数据结构和/或输出。

您的第一步是处理NUMID令牌,因为这些令牌具有关联值。您需要在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代码添加操作来执行操作。