LINUX.ORG.RU

[C][bison] Вернуть структуры из yyparse.

 ,


0

0

Есть связка flex/bison. Связка эта таскает текст не со стандартного ввода, а из строки, предоставляемой им другой функцией. Bison по большому счёту делает всего две вещи: собирает структуры из полученных токенов и матерится на синтаксические ошибки. Мне нужно как-то получать собранные им структуры. Первый это впихивать в правила bison'а return'ы. Но тогда во-первых получается, что функция которая должна возвращать int возвращает указатель (что как-то не красиво и запутано), а во-вторых она уже не вернёт 0 после успешного разбора и становится не понятно как отследить тот момент когда разбор завершился. Второй это создать некий внешний «стек» при помощи extern'а и писать в него указатели на структуры из yyparse, чтобы потом прочесть их из функции вызвавшей yyparse. Недостатком этого варианта является то что при вызове yyparse из нескольких нитей одновременно стек превратится в кашу (можно конечно залочить стэк на время его использования, а после этого скопировать его локально для вызывающей функции, но это по моему самый крайний случай, да и замок в таком месте обиден и явно не обоснован). Собственно как можно попытаться решить такую задачу?

★★★★★

Ответ на: комментарий от Sectoid

Хм... Вариант. И очень даже интересный. Сейчас попробую. Правда всё равно получается довольно громоздко.

KblCb ★★★★★
() автор топика

>Но тогда во-первых получается, что функция которая должна возвращать int возвращает указатель

Разве в bison'e нельзя поменять тип с помощью YYSTYPE? Или я о другом думаю?

anonymous
()
Ответ на: комментарий от anonymous

anonymous

Разве в bison'e нельзя поменять тип с помощью YYSTYPE? Или я о другом думаю?

YYSTYPE это тип семантического значения токена, а int это тип значения возвращаемого функцией.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от KblCb

с ходу могу посоветовать только это. но там неплохая отправная точка.

Sectoid ★★★★★
()

у меня делается так

// cpp:
Parser p;
while (yyparse(&p));

// ypp:
%parse-param { Parser * ptr }
....

expr: AXIOM  TURTLE { ptr->last.setAxiom($2); free($2); }
    | THETA  number { ptr->last.theta = $2; }
    | ANGLE  number { ptr->last.theta = M_PI * (360.0 / $2) / 180.0; }
    | ALPHA  number { ptr->last.alpha = $2; }
    | VAR   '=' turtle { ptr->last.r[$1[0]] = $3; free($3); }
    | MGL    MGLSTR { ptr->last.addMgl($2); }
    | ORDER  NUM    { ptr->last.setOrder($2); }
    ;

Никаких TLS не надо, ибо не кроссплатформенно.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Гм... А разве yyparse принимает что-то в качестве аргумента? Или это плюсовые особенности? Так или иначе тут плюсы, а значит скорее всего объедок и инкапсуляция. Мне как раз очень не хватает ООП.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от KblCb

Вот это делает так, чтобы принимало

%parse-param { Parser * ptr } 

Да это плюсы, но суть от этого не меняется. Parser это мой собственный класс, в Си у тебя это будет структура с данными.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Хм... Такое чувство что это то что мне надо. Спасибо. В C у меня не только структура с данными, но ещё и extern'ы (правда их наделал не bison, а flex, но легче не становится). так что TLS видимо придётся воскурить.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от Reset

%parse-param { Parser * ptr }

О, замечательно, не знал о таком. Спасибо.

Sectoid ★★★★★
()
Ответ на: комментарий от Reset

Уже спасает потихоньку. Пока всё компилится в нечто стабильно рушащееся в сегфолт где-то в недрах yylex. Похоже надо основательно переписать правила для лексера. Открыл свежую документацию по flex'у (до этого пользовался проверенными десятилетиями) и несколько примеров реинтерантных лексеров. Теперь медитирую на всё это.

KblCb ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.