首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >野牛规则定义

野牛规则定义
EN

Stack Overflow用户
提问于 2017-01-23 13:48:46
回答 1查看 437关注 0票数 0

我在用Bison编写的ASN.1编译器中有一个问题。

代码语言:javascript
复制
A   OCTET STRING (CONTAINING B)

编译器忽略包含B的数据,并将数据引用为八进制字符串,而不是将其引用为B。是当前的规则:

代码语言:javascript
复制
 OctetStringType :
    OCTET STRING Constraint                      { $$ = new     OctetString($3); } |
    OCTET STRING '{' NamedOctetList '}' Constraint { $$ = new OctetString($6); }
    ;

我试图创造一个新的规则:

代码语言:javascript
复制
OctetStringType :
    OCTET STRING '('ContentsConstraint')' {}|
    OCTET STRING Constraint                      { $$ = new OctetString($3); } |
    OCTET STRING '{' NamedOctetList '}' Constraint { $$ = new OctetString($6); }
    ;
ContentsConstraint :
   CONTAINING Type  {  }
   ;

当我试图打印结果时:

代码语言:javascript
复制
  OCTET STRING '('ContentsConstraint')' {printf("$$: %s\n",$$);}

我得到了A,我怎样才能访问B?我是否必须修改这些规则才能访问B?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-23 16:43:37

(我假设您正在修改现有的ASN.1语法,而不是自己编写的语法。)

$$是由语义行为计算的语义值。所以

代码语言:javascript
复制
OCTET STRING '('ContentsConstraint')' {printf("$$: %s\n",$$);}

根本没有意义;您没有为$$分配一个值,因此必须将其视为一个未定义的值。

在实践中,bison/yacc解析器在操作执行之前有效地执行了赋值$$ = $1; (这很有用,因为它意味着您不需要在操作中只编写它)。因此,在本例中,您要打印生产中的第一个符号的语义值(这是$1的意思),即终端OCTET。但是,令牌OCTET不太可能具有语义值;在大多数解析器中,从未使用关键字终端的语义值,因此没有必要分配它。

大多数bison/yacc派生程序都会遇到一些麻烦,以确保每个语义值都初始化为某个值,以防止编译器警告(旧版本没有这样做),但是某些东西从未被指定,应该被视为未初始化。简而言之,您的代码显示出未定义的行为,并且可以打印任何内容。

我假设您希望打印ContentsConstraint非终端的语义值。假设定义非终端的产品的语义操作都正确地为其赋值,则可以以$4的形式访问它,因为ContentsConstraint是规则中的第四个令牌。这意味着您至少需要修改您的规则。

代码语言:javascript
复制
ContentsConstraint :   CONTAINING Type  {  }

代码语言:javascript
复制
ContentsConstraint :   CONTAINING Type  { $$ = $2; }

否则,ContentsConstraint的值将是默认操作(即$1 )的结果,在本例中,该操作没有语义值,如上面所示。

我建议阅读野牛手册,至少前几页提到“语义操作”,并参考可能使概念更加清晰的示例。(阅读整本手册不应该花费太多时间,而且会更有用,但我知道,如今阅读手册被认为是过时的。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41807914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档