Compiler construction 野牛规则定义
我在用Bison编写的ASN.1编译器中遇到了一个问题Compiler construction 野牛规则定义,compiler-construction,bison,compiler-optimization,asn.1,Compiler Construction,Bison,Compiler Optimization,Asn.1,我在用Bison编写的ASN.1编译器中遇到了一个问题 A OCTET STRING (CONTAINING B) 编译器忽略包含B的数据,并将数据引用为八位字节字符串 而不是把它称为B。 以下是当前规则: OctetStringType : OCTET STRING Constraint { $$ = new OctetString($3); } | OCTET STRING '{' NamedOctetList '}'
A OCTET STRING (CONTAINING B)
编译器忽略包含B的数据,并将数据引用为八位字节字符串
而不是把它称为B。
以下是当前规则:
OctetStringType :
OCTET STRING Constraint { $$ = new OctetString($3); } |
OCTET STRING '{' NamedOctetList '}' Constraint { $$ = new OctetString($6); }
;
我尝试创建一个新规则:
OctetStringType :
OCTET STRING '('ContentsConstraint')' {}|
OCTET STRING Constraint { $$ = new OctetString($3); } |
OCTET STRING '{' NamedOctetList '}' Constraint { $$ = new OctetString($6); }
;
ContentsConstraint :
CONTAINING Type { }
;
当我尝试打印结果时:
OCTET STRING '('ContentsConstraint')' {printf("$$: %s\n",$$);}
我得了A。
如何访问B?是否必须修改这些规则才能访问B?(我假设您正在修改现有的ASN.1语法,而不是您自己编写的语法。)
$$
是由语义操作计算的语义值。所以
OCTET STRING '('ContentsConstraint')' {printf("$$: %s\n",$$);}
毫无意义;您尚未为$$
指定值,因此必须将其视为未定义的值
实际上,bison/yacc解析器有效地执行了赋值$$=$1代码>在执行操作之前(这很有用,因为这意味着当您只想在操作中执行操作时,不必编写代码)。因此,在本例中,您正在打印产品中第一个符号的语义值(这就是$1
的意思),即终端八位字节。然而,令牌八位字节
不太可能具有语义值;在大多数解析器中,从未使用关键字终端的语义值,因此分配它没有意义
大多数bison/yacc衍生物都会遇到一些麻烦,以确保每个语义值都被初始化为某个值,以防止编译器发出警告(旧版本没有这样做),但某些值从未被指定,应该被视为未初始化。简而言之,您的代码表现出未定义的行为,可以打印任何内容
我假设您想要打印ContentsConstraint
非终端的语义值。假设您对定义非终端的产品的语义操作都正确地为其分配了一个值,您可以将其作为$4
访问,因为ContentsConstraint
是规则中的第四个标记。这意味着您至少需要修改您的规则
ContentsConstraint : CONTAINING Type { }
到
否则,ContentsConstraint
的值将是默认操作的结果,即$1
,在本例中,它没有语义值,如上所述
我建议阅读,至少前几页“语义动作”,并参考可能使概念更清晰的示例。(阅读整个手册应该不会花费太多时间,而且会更有用,但我知道现在阅读手册被认为是过去时。)实际上,OCTET字符串(包含B)
是一个OCTET字符串
,而不是B
类型。只有在八位字节sting中传输的字节是B
的一些编码。
ContentsConstraint : CONTAINING Type { $$ = $2; }