Как построить массив с помощью Bison / Yacc и рекурсивного правила - PullRequest
2 голосов
/ 16 сентября 2009

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

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

и

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

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

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

Ответы [ 2 ]

6 голосов
/ 16 сентября 2009

Если у вас есть тип массива с операцией 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; }
2 голосов
/ 24 апреля 2011
%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;
    }
  ;
%%
...