1、yacc的yyparse()调用lex的yylex(
)取得token,将token压入堆栈;
2、yacc查看栈顶是否有可归约串,如没有,继续取得toke n入栈:这是移进(shift);
如果栈顶有可归约串,则归约为一个非终结符(在.y文件里定义的 ),并将该非终结符
入栈,然后继续(2),查看是否有可归约串,直到栈顶没有可归约 串:这是归约(reduce);
3、yacc对可归约串进行归约时,同时执行.y文件里对应产生 式的动作。
如产生式 Expression: | Expression PLUS Expression { $$=$1+$3; }
4、一个非终结符(如上面的Expression) ,它的产生式是非终结符最重要的性质定义,yacc
就是根据产生式进行"移进-归约"而运作的
5、一个非终结符同时可以关联一个值(sematic value),这个值的类型可以是int、char、
char*或任何其他结构和指针。值的类型在.yy中定义:
%union {
char cval;
char *sval;
int nval;
double fval;
}
yacc产生的代码将这个union用typedef成YYST YPE,同时定义一个全局变量yylval。在.lex文
件中可以用yylval.cval或yylval .sval等来设置对应的值。在.y文件里用
%token <nval> TOK 或
%type <nval> UNDETEM 来定义token或非终结符的类型后,该token的值$$或 $n就被定义为
YYSTYPE::nval类型,使用$$、$n就可以直接访问 到int或char *等类型了。
6、在.y文件的%left和%right可以定义左结合、右结合和优先级,如
%left PLUS MINUS
%left TIMES DIVIDE
%right POWER
定义了结合的方向,同时POWER的优先级比TIMES 、DIVIDE,TIMES、DIVIDE比PLUS
、MINUS高。
<script type="text/javascript">
</script>
2、yacc查看栈顶是否有可归约串,如没有,继续取得toke
如果栈顶有可归约串,则归约为一个非终结符(在.y文件里定义的
入栈,然后继续(2),查看是否有可归约串,直到栈顶没有可归约
3、yacc对可归约串进行归约时,同时执行.y文件里对应产生
如产生式 Expression: | Expression PLUS Expression { $$=$1+$3; }
4、一个非终结符(如上面的Expression)
就是根据产生式进行"移进-归约"而运作的
5、一个非终结符同时可以关联一个值(sematic value),这个值的类型可以是int、char、
char*或任何其他结构和指针。值的类型在.yy中定义:
%union {
char cval;
char *sval;
int nval;
double fval;
}
yacc产生的代码将这个union用typedef成YYST
件中可以用yylval.cval或yylval
%token <nval> TOK 或
%type <nval> UNDETEM 来定义token或非终结符的类型后,该token的值$$或
YYSTYPE::nval类型,使用$$、$n就可以直接访问
6、在.y文件的%left和%right可以定义左结合、右结合和优先级,如
%left PLUS MINUS
%left TIMES DIVIDE
%right POWER
定义了结合的方向,同时POWER的优先级比TIMES