Проблема с правильными рекурсивными правилами с Бизоном - PullRequest
0 голосов
/ 07 ноября 2018

Я реализовал с помощью зубров управление многомерным массивом этот кусок кода работает, используя левые рекурсивные правила тем не мение. В руководстве указано, что лучше использовать те, что справа. ссылка: Бизон Рекурсивные правила

однако теперь, если я использую правильное правило, массив не анализируется правильно. проблема в том, что когда я использую правильное правило, внутренний массив a [2,3] возвращает 4 измерения вместо 2, а другой массив x [,] не имеет измерения.

мой вопрос: почему этот кусок кода не работает с правильным рекурсивным правилом?

неправильное рекурсивное ошибочное правило:

argList
    : expr              {stackNode [ kstack++ ] = $1 ;  }
    | argList ',' expr  {stackNode [ kstack++ ] = $3 ;  }

Источник выборки:

xy[1, a[2,3] ] =  4  ;

грамматика зубров:

argList
    : expr              {stackNode [ kstack++ ] = $1 ;  }
    | expr ',' argList  {stackNode [ kstack++ ] = $1 ;  }
;   

statement                                                
    : tPV
    | expr tPV  { $$=$1; } 
;

expr
    : tINTEGER                  { $$ = new_tINTEGER ( $1 ) ;    }
    | tID '[' argList ']'
    {   
        void** n=(void**) malloc ( sizeof(void**)*kstack ) ;    
        for(int j=0,  i=kstack-1    ;   i>=0    ;   i-- )   n[j++] = (void*) stackNode[i] ;
        $$ = new_tArrayArgList ( $1,kstack,n ) ;
        kstack=0;
    }   
    | expr tEQ      expr            { $$ = new_tBINOP ( tEQ,$1,$3) ;    /*  =   */} 

ссылка:

Как построить массив с бизоном / яком и рекурсивным правилом

Левые рекурсивные правила в контекстно-свободной грамматике

С уважением Claudio

1 Ответ

0 голосов
/ 08 ноября 2018

Проблема в том, что вы используете глобальные переменные stackNode и kstack для отслеживания списков аргументов. Это не реентерабельно, поэтому, когда у вас есть вложенные списки аргументов, обработка внутреннего списка поглощает и повреждает состояние внешнего списка, что приводит к мусору. Это не зависит от рекурсии влево и вправо, хотя в двух случаях будет разная коррупция.

Решение состоит в том, чтобы не использовать глобальные переменные - вернуть необходимые значения в $$:

argList
    : expr              { $$ = new_empty_deque();
                          push_back($$, $1);  }
    | expr ',' argList  { $$ = $3; push_front($$, $1); }
;   

поочередно (и выше), используйте леворекурсивное правило:

argList
    : expr              { $$ = new_empty_deque();
                          push_back($$, $1);  }
    | argList ',' expr  { $$ = $1; push_back($$, $3); }
;   
...