Search code examples
parsingbisonflex-lexerparser-generatorcompiler-compiler

How to create top-down "tree" construction using bison?


I've found this example, but it creates tree bottoms-up. Is it possible to create tree topdown using bison, flex?

Pseudocode:

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)); }

Solution

  • You can do pretty much exactly what you describe with btyacc. You can write:

    %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;
    }
    

    You can do the same thing in bison, but you have to use embedded actions with explicit type tags:

    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); }