0

У меня проблема в компиляторе ASN.1, написанном в Bison.Определение правил Bison

A OCTET STRING (CONTAINING 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?

+0

На самом деле, 'OCTET STRING (CONTAINING B)' is «OCTET STRING», а не тип «B». Только байты, переносимые в октете, являются некоторой кодировкой «B». – Henry

ответ

1

(я предполагаю, что вы изменяете существующий грамматике 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é.)

Смежные вопросы