Как создать нисходящую "древовидную" конструкцию с использованием зубров?
Я нашел этот пример, но он создает дерево снизу вверх. Можно ли создать дерево сверху вниз, используя bison, flex?
псевдокод:
block(parent):
{ current = new Block(); parent.addBlock(this); }
BLOCK_BEGIN_TOKEN block_content(current) BLOCK_END_TOKEN
;
block_content(parent)
: block_content(parent) statement(current)
| block_content(parent) block(current)
| statement(parent)
| block(parent)
;
statement(parent)
: STATEMENT_TOKEN { parent.addStatement(new Statement($1)); }
3 ответа
Вы можете сделать в точности то, что вы описываете с помощью btyacc. Ты можешь написать:
%union {
Statement *stmt;
Block *blk;
}
%token BLOCK_BEGIN_TOKEN BLOCK_END_TOKEN
%token<stmt> STATEMENT_TOKEN
%type block(<blk>) block_content(<blk>) statement(<blk>)
%%
input: block(new Block())
;
block($parent):
BLOCK_BEGIN_TOKEN block_content(new_block($parent)) BLOCK_END_TOKEN
;
block_content($parent)
: block_content($parent) statement($parent)
| block_content($parent) block($parent)
| statement($parent)
| block($parent)
;
statement($parent)
: STATEMENT_TOKEN { $parent->addStatement($1); }
%%
Block *new_block(Block *parent) {
Block *b = new Block();
parent->addBlock(b);
return b;
}
Вы можете сделать то же самое в зубре, но вы должны использовать встроенные действия с явными тегами типа:
block:
BLOCK_BEGIN_TOKEN { $<blk>$ = new_block($<blk>0); } block_content BLOCK_END_TOKEN
;
block_content
: block_content { $$=$0; } statement
| block_content { $$=$0; } block
| statement
| block
;
statement
: STATEMENT_TOKEN { $<blk>0->addStatement($1); }
Итак, как в вашем примере, есть ли у yacc / bison способ параметризации нетерминалов в произведениях, приравнивая это к вызову сгенерированной функции?
Это было бы нет; вот ссылка на синтаксис.
Имейте в виду, что yacc / bison генерирует парсер с уменьшением сдвига, а не рекурсивный спуск. Если вы хотите сделать что-то подобное, генератор рекурсивного спуска с большей вероятностью разрешит это. Вот их список.
Нет. Парсер yacc/bison - это парсер LALR(1). Это восходящие парсеры.
Я не понимаю, почему тебя это волнует.