(я предполагаю, что вы изменяете существующий грамматике ASN.1, а не тот, который вы написали сами.)
$$
семантическое значение вычисляемого семантическим действием. Таким образом,
OCTET STRING '('ContentsConstraint')' {printf("$$: %s\n",$$);}
не имеет никакого смысла; вы не присвоили значение $$
, поэтому его следует считать неопределенным значением.
На практике анализатор bison/yacc эффективно выполнил присвоение $$ = $1;
до того, как действие было выполнено (что полезно, потому что это означает, что вам не нужно писать это, когда это все, что вы хотите сделать в действие). Таким образом, в этом случае вы печатаете семантическое значение первого символа в производстве (что и означает $1
), который является терминалом OCTET
. Однако маловероятно, что токен OCTET
имеет семантическое значение; в большинстве парсеров семантическое значение терминалов ключевых слов никогда не используется, поэтому нет смысла его назначать.
Большинство производных бизон/Yacc пойти на некоторые проблемы, чтобы гарантировать, что каждое семантическое значение инициализируется что-то для того, чтобы предотвратить предупреждения компилятора (старые версии не сделали этого), но что-то никогда не определены и следует рассматривать как неинициализированную. Короче говоря, ваш код демонстрирует Undefined Behavior и может печатать что угодно.
Я полагаю, что вы хотите напечатать семантическое значение неконцевого терминала ContentsConstraint
. Предполагая, что ваши семантические действия для производств, которые определяют, что нетерминал все правильно присваивают значение для него, вы можете получить к нему доступ как $4
, так как ContentsConstraint
является четвертым маркером в правиле. Это означает, что по крайней мере нужно изменить ваше правило
ContentsConstraint : CONTAINING Type { }
в
ContentsConstraint : CONTAINING Type { $$ = $2; }
поскольку в противном случае значение ContentsConstraint
будет результатом действия по умолчанию, который $1
, который в данном случае делает не имеют семантического значения, как указано выше.
Я рекомендую прочитать bison manual, по крайней мере, первые несколько страниц вплоть до «Семантические действия» со ссылкой на примеры, которые могут сделать понятные понятные понятия. (Чтение всего руководства не должно тратить слишком много времени и было бы еще более полезным, но я знаю, что в настоящее время в руководствах по чтению рассматриваются passé.)
На самом деле, 'OCTET STRING (CONTAINING B)' is «OCTET STRING», а не тип «B». Только байты, переносимые в октете, являются некоторой кодировкой «B». – Henry