LINUX.ORG.RU

[yacc][lemon][C] разбор вложенных структур

 ,


0

1

Пишу на lemon/flex разбор С-syntax структур, например:

struct some0 {
        int var0;l
        struct some1 {
               int var1;
               int var2;
       };
       int var3;
};
Пусть у нас есть правило lemon/yacc:
struct ::= STRUCT name OBRACE definitions EBRACE SEMICOLON.
и некая функция new_struct_node(char* name); Как сделать так, чтобы знать какой уровень текущий, и в какое место в дереве вставлять эту структуру или переменную?

Вот parse.y: http://paste.pocoo.org/show/549470/ tree.c http://paste.pocoo.org/show/549472/ cparse.h http://paste.pocoo.org/show/549471/

★★★★★

Последнее исправление: XVilka (всего исправлений: 1)

Использовать extra_argument?

%extra_argument { struct mycontext *context }

Этот аргумент нужно будет передавать в функцию Parse() 4-м параметром. И он будет доступен в грамматике. То есть его можно будет передать дальше в new_struct_node: new_struct_node(context, A.sval), ну и внутри new_struct_node уже что-то делать.

Посмотрите в исходниках SQLite, там вроде бы так все сделано

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

Гм. Коряво как-то выразился. В общем, смысл месыджа таков: это надо делать в С коде. Начинаем парсить структуру - помечаем это в контексте. Если в процессе (до окончания) парсенья структуры появляется еще структура, значит она вложенная

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

Я конечно ничо не знаю про лемон, но разве не должен recursive descent parser в rule action иметь код, который к-л образом возвращает ветку дерева, которая строится с помощью уже построенных [не]терминалов ${n}? Смысл тогда вообще использовать parser generator?

//yacc
%%
struct: STRUCT name '{' definitions '}' { $$ = mkstructnode($2, $4); }
      ;
%%
extern StructInfo *defstruct(const char *tag, List *definitions);
Тогда весь AST можно вытянуть за $1 из %start

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

ага, разобрался с этим же для lemon. Один вопрос только, как теперь добавлять дочерние элементы в структуры, если сама структура создается парсером только после её закрывающей скобки? «};»

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

Когда приходит время создавать структуру текущего уровня, все ее дочерние элементы уже созданы и находятся в ${n}. Другими словами: сначала происходит редукция составляющих нетерминалов (естественным образом, по-порядку следования), только потом, при получении '}', редуцируется текущее правило. В этот же момент исполняется код правила. Осталось только сунуть составляющие части в соответствующие поля структуры. Структуру создавай и заполняй сам в rule action и возвращай ее как результат правила. Не знаю, как это в лемоне делается. И да, парсер ничего не знает про твое дерево и ничего не создает; его задача выполнить rule action, когда нужно, и вместо нетерминалов подставить результат /их/ rule action'ов.

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

я делаю так

deflist(A) ::= deflist(B) def(C). { B->next = C; A = B }
где тип операндов - связный список, то есть добавляем по одному элементу. Но парсер почему-то добавляет только первый и последний дочерний элементы.

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

в обратном порядке работает:

{ C->next = B; A = C; }
но список получается тогда тоже в обратном порядке. Как сделать чтобы и нормально работал, и порядок тоже был прямой?

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

Недоглядел:

{ C->next = B; A = C }
Результат будет в обратном порядке, можно при получении зеркалить, можно добавлять в конец, что может быть затратно для больших списков, можно просто иметь ввиду. А при B->next = C ты всегда теряешь хвост списка на C, отсюда и первый+последний.

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

Пусть будет обратный, какая разница, если ты об этом знаешь.

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

да, я уже понял как это сделать, спасибо!

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