2016-03-15 2 views
1

Я пытаюсь написать небольшой компилятор, который может разобрать некоторые команды, которые я набираю.Как узнать значение переменной в бизоне при отладке с помощью GDB?

Команда, которую я пытаюсь разобрать это:

create class something = create class do_something ; 

Мой код будет выглядеть примерно так:

grammar : my_grammar 
     { 
      list<Class1 *> *obj = new list<Class1 *>; 
      obj->push_back($1); 
     } 

my_grammar : my_definition SEMICOLON 
      { 
       report("something detected!"); 
       $$ = $1; 
      } 

my_definition : CREATE CLASS class_name EQU class_expression 
       { 
        $5->setClassName(*$3); 
        $$ = $5; 
       } 

class_expression : CREATE CLASS operand_name 
       { 
        $$ = new OperandClass(); 
        $$->setOperationType("createClass"); 
        $$->setOperandName(*$3); 
        } 

Однако, когда я пытаюсь вызвать парсер где-то еще, я не могу получите Class, который я определил ранее.

Я предполагаю, что в парсере должно быть что-то не так и проделали некоторую отладку с помощью GDB. Но я просто не могу войти в функцию push_back(), и я не могу правильно напечатать информацию obj.

Итак, мне интересно, есть ли способ, которым я могу получить значение $$ или $1 при использовании GDB. Просто введите p $$, чтобы напечатать что-то еще.

+2

Посмотрите на код спагетти, из которого выбивается бизон.Нетрудно определить, какие переменные/структуры представляют собой заполнители $$ и $ 1. bison превращает грамматику в робо-сгенерированный C++, заменяя все элементы yacc-y контейнерами и объектами C++. Как только вы выясните, что это такое, вы будете печатать их содержимое точно так же, как и любые другие объекты ». –

+0

@SamVarshavchik Я просто посмотрю на код спагетти и найду в нем соответствующую строку 'obj-> push_back ($ 1)' в то время как '$ 1' заменяется на' (((yyGLRStackItem const *) yyvsp) [YYFILL ((1) - (1))]. Yystate.yysemantics.yysval.OperandClass) '. Однако, когда я установил точку останова в сгенерированном файле 'cpp' и попытаюсь напечатать значение, программа всегда будет возвращаться к файлу' ypp', который я написал, и говорит: «Без символа YYFILL в текущем контексте». У вас есть идеи об этом? – laxus

+1

Это потому, что YYFILL - это, скорее всего, макрос. –

ответ

0

Простейший способ, вероятно, объявление переменной того же типа, что и ваше правило (имеет этот тип) и присвоение его.

%union { 
    int I; 
} 
%type<I> rule whatever 

rule: whatever { 
    int foo = $1; 
    // printf("%d", foo); 
    $$ = $1; 
} 

Вы можете либо увидеть его в отладчике, либо просто распечатать его.

Отладчик не может войти внутрь push_back или другими стандартными функциями, если у вас нет стандартной информации об отладке библиотеки.

Что касается вашего вопроса в целом, ваш obj является локальным для правила, которое трансформируется в функцию Bison и не видно за его пределами, если вы не храните его в другом месте, например. в глобальном масштабе.

+0

@ Ответ участника гораздо лучше. Это легко запомнить: для '$$' использовать 'yyval. '. Для '$ ' use 'yyvsp [ - 1]. '. – user2259432

2

Если вы используете бизон с шаблонами C, зубр имеет переменную yyval и массив yyvsp, оба типа YYSTYPE, который мы определяем, используя %union опции в бизоне parser.y файла. Правило $$ задается членом объединения yyval, а символы в производстве являются членами в массиве yyvsp. Например, для объединения:

%union { 
    int t1; 
    float t2; 
} 

%type <t1> nt1; 
%type <t2> nt2; 
%% 
input : nt1 | nt2; 
nt1 : CONSTANT { $$ = $1; } ; 
nt2 : FCONSTANT { $$ = $1 }; 
%% 
int main() { yyparse(); } 

при использовании GDB:

  1. Вы можете обратиться к левой руке производства, например nt1 от его типа, т.е. $$ для nt1 может быть названо по yyval.t1
  2. $i на RHS можно назвать: yyvsp[i - t].type, где i - индекс символа, на который должны быть указаны, и t - общее количество символов (терминалов и нетерминалов) в производстве.

Так, например, $1 оба правила могут упоминаться под yyvsp[1-1].t1 и yyvsp.[0].t2 соответственно.