# $Id: PlumheadPAST.tg 17145 2007-02-22 14:11:04Z bernhard $

grammar Plumhead::PAST::Grammar is TGE::Grammar;

# Generate PAST-pm from Plumhead parse tree

transform past (ROOT) :language('PIR') {

    node = node['program']
    .local pmc past
    past = new 'PAST::Block'
    past.'init'( 'node' => node, 'name'=>'plumhead' )
    
    .local pmc past_program
    past_program = tree.'get'('past', node, 'Plumhead::Grammar::program')
    past.'push'(past_program)

    .return (past)
}

# TODO: handle multiple code and sea blocks
transform past (Plumhead::Grammar::program) :language('PIR') {

    .local pmc past
    past = new 'PAST::Stmts'
    past.'init'( 'node' => node )

    $P0 = node['SEA']
    if null $P0 goto handled_sea
        .local pmc past_sea
        past_sea = tree.'get'('past', $P0, 'Plumhead::Grammar::SEA')
        past.'push'(past_sea)
    handled_sea:

    $P0 = node['code']
    if null $P0 goto handled_code
        .local pmc past_code
        past_code = tree.'get'('past', $P0, 'Plumhead::Grammar::code')
        past.'push'(past_code)
    handled_code:

    .return (past)
}

transform past (Plumhead::Grammar::SEA) :language('PIR') {

    .local string val
    val = node
    .local pmc code_string
    code_string = new 'PGE::CodeString'
    ( val ) = code_string.'escape'( val )

    .local pmc past_val
    past_val = new 'PAST::Val'                             
    past_val.'init'( 'name' => val, 'vtype' => '.Undef' )                              

    .local pmc past                                                  
    past = new 'PAST::Op'
    past.'init'( past_val, 'node'=> node, 'pirop' => 'print' )  

    .return (past)
}

transform past (Plumhead::Grammar::code) :language('PIR') {

    .local pmc past
    past = new 'PAST::Stmts'
    past.'init'( 'node' => node )

    $P0 = node['statement']
    if null $P0 goto handled_statement
        .local pmc iter
        iter = new .Iterator, $P0
        iter_loop:
            unless iter goto iter_end
            .local pmc cnode, past_else_block, past_expression, past_echo, past_if, past_if_block, past_sea
            cnode = shift iter
            if null cnode goto iter_loop
                 $P1 = cnode['ECHO']
                 if null $P1 goto no_echo
                     $P2 = cnode['expression']
                     if null $P2 goto iter_loop
                         past_expression = tree.'get'('past', $P2, 'Plumhead::Grammar::expression')
                         if null past_expression goto iter_loop
                         past_echo = new 'PAST::Op'
                         past_echo.'init'( past_expression, 'node'=> node, 'name' => 'print' )  
                         past.'push'(past_echo)
                         goto iter_loop
                 no_echo:
                 $P1 = cnode['IF']
                 if null $P1 goto no_if
                     $P2 = cnode['expression']
                     past_expression = tree.'get'('past', $P2, 'Plumhead::Grammar::expression')
                     if null past_expression goto iter_loop
                     # past_if_block takes care of the <statement>
                     past_if_block = tree.'get'('past', cnode, 'Plumhead::Grammar::code')
                     past_if = new 'PAST::Op'
                     past_if.'init'( past_expression, past_if_block, 'node'=> node, 'pasttype' => 'if' )  
                     $P3 = cnode['else_clause']
                     if null $P3 goto no_else_clause
                         $P4 = $P3[0]
                         past_else_block = tree.'get'('past', $P4, 'Plumhead::Grammar::code')
                         past_if.'push'(past_else_block)
                     no_else_clause:
                     past.'push'(past_if)
                     goto iter_loop
                 no_if:
                 $P1 = cnode['inline_sea']
                 if null $P1 goto no_inline_sea
                     $P2 = $P1['SEA']
                     past_sea = tree.'get'('past', $P2, 'Plumhead::Grammar::SEA')
                     past.'push'(past_sea)
                     goto iter_loop
                 no_inline_sea:
                 # unknown statements are ignored
                 goto iter_loop
         iter_end:

    handled_statement:

    .return (past)
}

transform past (Plumhead::Grammar::expression) :language('PIR') {

    .local pmc past

    $P0 = node['expression']
    if null $P0 goto no_expression_1
    past = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
    goto handled_expression
    no_expression_1:

    $P0 = node['DOUBLEQUOTE_STRING']
    if null $P0 goto no_DOUBLEQUOTE_STRING
    past = tree.'get'('past', $P0, 'Plumhead::Grammar::DOUBLEQUOTE_STRING')
    goto handled_expression
    no_DOUBLEQUOTE_STRING:

    $P0 = node['SINGLEQUOTE_STRING']
    if null $P0 goto no_SINGLEQUOTE_STRING
    past = tree.'get'('past', $P0, 'Plumhead::Grammar::SINGLEQUOTE_STRING')
    goto handled_expression
    no_SINGLEQUOTE_STRING:

    $P0 = node['NUMBER']
    if null $P0 goto no_NUMBER
    past = tree.'get'('past', $P0, 'Plumhead::Grammar::NUMBER')
    goto handled_expression
    no_NUMBER:

    $P0 = node['adding_expression']
    if null $P0 goto no_adding_expression
        .local pmc past_mult, summand, summand_0, past_summand_0
        summand = $P0['summand']
        if null summand goto no_summand
            past_mult = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
            summand_0 = summand[0]
            .local string add_op, pirop
            pirop = 'n_add'
            add_op = summand_0['ADD_OP']
            if add_op != '-' goto not_minus
                pirop = 'n_sub'
            not_minus:
            add_op = 'infix:' . add_op 
            past_summand_0 = tree.'get'('past', summand_0, 'Plumhead::Grammar::expression')
            past = new 'PAST::Op'
            past.init( past_mult, past_summand_0, 'name' => add_op, 'pirop' => pirop )
            goto handled_expression
        no_summand:
        past = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
    goto handled_expression
    no_adding_expression:

    $P0 = node['multiplying_expression']
    if null $P0 goto no_multiplying_expression
        .local pmc past_unary, multiplicand, multiplicand_0, past_multiplicand_0
        multiplicand = $P0['multiplicand']
        if null multiplicand goto no_multiplicand
            past_unary = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
            multiplicand_0 = multiplicand[0]
            .local string mul_op, pirop
            pirop = 'n_mul'
            mul_op = multiplicand_0['MUL_OP']
            if mul_op != '/' goto not_div
                pirop = 'n_div'
            not_div:
            mul_op = 'infix:' . mul_op 
            past_multiplicand_0 = tree.'get'('past', multiplicand_0, 'Plumhead::Grammar::expression')
            past = new 'PAST::Op'
            past.init( past_unary, past_multiplicand_0, 'name' => mul_op, 'pirop' => pirop )
            goto handled_expression
        no_multiplicand:
        past = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
    goto handled_expression
    no_multiplying_expression:

    $P0 = node['unary_expression']
    if null $P0 goto no_unary_expression
        $P1 = $P0['postfix_expression']
        if null $P1 goto handled_expression
            $P2 = $P0['UNARY_MINUS']
            if null $P2 goto no_minus
                past = new 'PAST::Op'
                .local pmc past_expression
                past_expression = tree.'get'('past', $P1, 'Plumhead::Grammar::expression')
                past.init( past_expression, 'node' => $P0, 'name' => 'prefix:-' )
                goto handled_expression
            no_minus:
            $P2 = $P1['expression']
            if null $P2 goto no_expression
                past = tree.'get'('past', $P2, 'Plumhead::Grammar::expression')
                goto handled_expression
            no_expression:
            past = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
            goto handled_expression
    no_unary_expression:

    $P0 = node['postfix_expression']
    if null $P0 goto no_postfix_expression
    past = tree.'get'('past', $P0, 'Plumhead::Grammar::expression')
    goto handled_expression
    no_postfix_expression:

    handled_expression:

    .return (past)
}


transform past (Plumhead::Grammar::DOUBLEQUOTE_STRING) :language('PIR') {

    .local pmc past
    past= new 'PAST::Val'                             
    .local string val
    val = node
    .local pmc code_string
    past.'init'( 'name' => val, 'vtype' => '.Undef' )                              

    .return (past)
}


transform past (Plumhead::Grammar::SINGLEQUOTE_STRING) :language('PIR') {

    .local pmc past
    past = new 'PAST::Val'                             
    .local string val
    val = node
    .local pmc code_string
    past.'init'( 'name' => val, 'vtype' => '.Undef' )                              

    .return (past)
}

transform past (Plumhead::Grammar::NUMBER) :language('PIR') {

    .local pmc past
    past = new 'PAST::Val'                             
    .local string val
    val = node
    past.'init'( 'name' => val, 'vtype' => '.Float', 'ctype' => 'n+' )                              
    .return (past)
}

