1、嵌入式动作在规则内变成一个符号,所以它的值($$)像任何其他的符号一样对于规则末端的动作都是可以用的。
如:
thing: A {$$=17;} B C
{printf(%d"",$2);}
在使用嵌入式动作时,如果正在使用“%union”和有类型的符号值,则在引用动作值时就得将值放入尖括号内,例如将它放入嵌入式动作时的$<type>$,以及在规则末端动作中引用它的$<type>3。
2、明确的符号类型
通过在¥和符号数字之间使用或在2个$之间的尖括号内插入类型名,如$<xxx>3或$<xxx>$,YACC允许为符号值引用声明一个明确的类型。3、标记值
YACC语法分析程序中每个符号都有一个相关的值。在语法分析程序中,一定要声明所有具有值的标记的值类型。
%union声明标识符号值的所有可能的C类型。将拷贝到输出文件的YYSTYPE类型的C联合类型声明中。
4、yyerror()提供错误报告例程
5、YYABORT使得语法分析例程yyparse()以一个非零值立即返回,显示失败
6、YYACCEPT:yyparse()以一个零值返回,显示成功。
7、yyparse()语法分析程序的入口点,成功返回零,失败返回非零
8、YACC的冲突,YACC只能向前看一个标记。如下的没有冲突:tgt
start:x B
|y C;
x: A;
y: A;
9、移进/归约冲突
stmt:if '(' cond ')' stmt
|if '(' cond ')' stmt ELSE stmt
if (cond) if (cond) stmt ELSE stmt如何理解
1)if (cond){if (cond) stmt ELSE stmt}
2)if (cond){if (cond) stmt }ELSE stmt
设置明显的优先级阻止YACC发布警告
%nonassoc LOWER_THEN_ELSE或%nonassoc THEN
%nonassoc ELSE
ELSE优先级比LOWER_THEN_ELSE高,因为移进优先级必须高于归约优先级
1、继承的属性
属性以标记值开始,即从语法分析树的叶子开始。每次规则被归约时,信息概念性地在语法分析树中上移。并且它的动作根据规则右侧符号值勤合成符号($$)的值。
例如:
declaration:class type namelist;
class: GLOBAL {$$=1;}
|LOCAL {$$=2;}
;
type:REAL {$$=1;}
|INTEGER {$$=2;}
;
namelist:NAME {mksymbol($0,$-1,$1);}
|namelist NAME {mksymbol($0,$-1,$2);}
yacc允许访问它的左侧的内部堆栈上的符号($0,$-1,$-2....),上例中$0指在namelist产生式的符号之前被堆栈的type的值。$0指class。
继承的符号类型必须在动作代码中采用明确的类型提供类型名。
2、文字块
%{
.....
%}
内容被原封不动地拷贝到生成的C源文件中靠近开头的部分。
3、优先级和结合性
结合性:%left左结合,%right右结合,%nonassoc非结合操作
通过声明结合性的顺序决定优先级,声明在后的优先级高
4、左、右递归,左递归更适合于YACC处理
exprlist:exprlist ','expr;
exprlist:expr ','exprlist;
5、规则尾端有明确的优先级:
expr:expr '*' expr
|expr '-' expr
|'-'expr %prec UMINUS;
6、符号类型
YACC在内部将每个值做为包括所有类型的C联合类型来声明。在%union声明中列出所有的类型,YACC将其转变为称为YYSTYPE的联合类型的类型定义。对于值已在动作代码中设置和使用的符号,必须声明它的类型。对非终结符使用%type(如%type<dval> expression),对标记即终结符使用%token,%left,%right,%nonassoc,(如:%token<dval>REAL )。在使用$$、$1等引用值,YACC会自动使用联合的适当字段。