Как построить массив с помощью Bison/Yacc и рекурсивного правила

С Bison я понял, как собрать все в одну длинную строку следующим образом:

arg_list:
    WORD arg_list { strcat( $1, "IFS" ); $$ = strcat($1, $2); }  |
    WORD
    ;

и:

WORD arg_list { printf("%s, %s\n", $1, $2); }

Но проблема в том, что мне придется снова разделить 2 доллара во втором правиле, чтобы проанализировать его. Есть ли способ заполнить массив, а не просто использовать конкатенацию? Я иду об этом неправильно?

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


person Kyle Brandt    schedule 15.09.2009    source источник
comment
Вы должны создавать списки лево-рекурсивно с помощью парсеров LR, таких как Bison, а не право-рекурсивно. В противном случае производственный стек должен содержать каждый элемент списка.   -  person user207421    schedule 21.07.2015


Ответы (1)


Если у вас есть тип массива с операцией push_front, это тривиально:

arg_list:
    WORD arg_list { $$ = $2.push_front($1); }
    WORD { $$ = new Array<string>($1); }

без этого требуется больше работы. Вы можете использовать вектор и добавить строки в конце (которые будут в обратном порядке). Или вы можете использовать связанный список (что проще, если вы используете прямой C):

arg_list:
    WORD arg_list { $$ = malloc(sizeof(struct list_elem));
                    $$->next = $2;
                    $$->val = $1; }
    WORD          { $$ = malloc(sizeof(struct list_elem));
                    $$->next = 0;
                    $$->val = $1; }
person Chris Dodd    schedule 15.09.2009
comment
Это все прямо C, второй в основном имеет смысл, но я не дошел до той части, где у $$ есть члены, знаете, что я мог бы найти в Google, чтобы найти это? - person Kyle Brandt; 16.09.2009
comment
$$ — это просто переменная типа, объявленного в объявлении %type этого правила, или YYSTYPE, если объявление %type отсутствует. Обычно это будет «список структур *» для arg_list, поэтому «$$-›next» и «$$-›val» будут элементами объекта списка, на который указывает. В случае C++ это намного сложнее, в зависимости от того, как вы определили вещи с потенциальными ссылками и еще чем-то. - person Chris Dodd; 18.09.2009