如何给 lex 和 yacc 中的文字一个索引值?

How to give an index value to literals in lex and yacc?

假设我有如下语法:

dish: fruit type ';';
fruit: "apple" | "strawberry" | "pear";
type: "pie" | "cheesecake" | "flan";

...我有一个功能来存储这些菜:

bool storeDish(int fruit, int type);

我如何有效地告诉 lex 或 yacc(我不知道是哪个)我希望 "apple" 的值为 0,"strawberry" 的值为 1,"pear" 的值为 2,"pie" 的值为 0,"cheesecake" 的值为 1,"flan" 的值为 2?

您可以在 %union 中定义一个数字类型,将您的非终结符定义为该数字类型,存储每个水果和类型的值,然后在您的菜肴规则中按索引访问它们。最好使用枚举,但这里有一个例子。

/* Define types, you will need to define one for each type of nonterminal */
%union
{
    int     numeric;
}

/* Specify the type of the nonterminal */
%type<numeric> fruit type

...

%%

...

/* Fruits value accessible by  and type by  */
dish
    : fruit type ';';
        { storeDish(, ); }
    ;

/* Assign each fruit and type a numeric value */
fruit
    : "apple" 
        { $$ = 0; }
    | "strawberry" 
        { $$ = 1; }
    | "pear"
        { $$ = 2; }
    ;
type
    : "pie" 
        { $$ = 0; }
    | "cheesecake"
        { $$ = 1; } 
    | "flan"
        { $$ = 2; }
    ; 

http://dinosaur.compilertools.net/bison/bison_6.html#SEC53

@Joe,或者你可以让 yylex 识别这些词,把在 yylval 中看到的水果的枚举值放在 yylval 中,并给 yacc 令牌 FRUIT。使用 FRUIT 的产品的 C 代码现在可以访问在 yylval 中看到的水果类型:

fruits:
    fruits fruit
    | fruit  
    ;
fruit : FRUIT           {if (==1) printf("seen strawberry\n"); }

(注意:我的 yacc 已经生锈了;希望我没有出错。)