Как построить массив с помощью 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, а затем очистить память.
Решение
Если у вас есть тип массива с операцией 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; }
Другие советы
%union {
char *char_ptr;
}
%token STRING
%type <char_ptr> STRING string
%%
...
string:
STRING /* Lexic analyzer return STRING and set yylval = yytext; */
| string STRING
{ char *str = (char*) malloc(strlen($1) + strlen($2) + 1);
strcpy(str, $1);
strcat(str, $2);
free($2);
free($1);
$$ = str;
}
;
%%