class C99::Grammar::Actions;
method TOP($/) { for $<external_declaration> { my $fun := $( $_ );
## Look for the "main" function, and set that as the result ## object. if $fun.name() eq 'main' { make $fun; } } }
method external_declaration($/, $key) { make $( $/{$key} ); }
method declaration($/) { my $past := PAST::Stmts.new( :node($/) );
for $<init_declarator> { $past.push( $( $_ ) ); } make $past; }
method init_declarator($/) { make $( $<declarator> ); }
method function_definition($/) { my $past := PAST::Block.new( :blocktype('declaration'), :node($/) ); my $decl := $( $<declarator> ); $past.name( $decl.name() );
my $body := $( $<compound_statement> ); $past.push($body); make $past; }
method declaration($/) {
}
method declarator($/) { make $( $<direct_declarator> ); }
method direct_declarator($/) { my $past := $( $<declarator_prefix> ); #my $past := $( $<declarator_suffix>[0] ); #$past.name($pref.name()); make $past; }
method declarator_prefix($/, $key) { make $( $/{$key} ); }
method declarator_suffix($/, $key) { make $( $/{$key} ); }
method parameter_type_list($/) { my $past := $( $<parameter_list> ); if $<vararg> { $past.push( PAST::Var.new( :name('@vararg'), :slurpy(1), :scope('parameter'), :node($/) ) ); } make $past; }
method parameter_list($/) { ## create the function block here already; it's needed to store the parameters my $past := PAST::Block.new( :blocktype('declaration'), :node($/) ); for $<parameter_declaration> { $past.push( $( $_ ) ); } make $past; }
method parameter_declaration($/, $key) { make $( $/{$key} ); }
method statement($/, $key) { make $( $/{$key} ); }
method jump_statement($/, $key) { if $key eq 'return' { my $past := PAST::Op.new( :pirop('return'), :node($/) ); if $<expression> { $past.push( $( $<expression>[0] ) ); } make $past; } else { $/.panic("$key is not implemented!"); } }
method for1_statement($/) { my $past := PAST::Stmts.new( :node($/) ); my $body := $( $<statement> ); my $cond; if $<cond> { $cond := $( $<cond>[0] ); } else { # a missing condition is true $cond := PAST::Val.new( :returns('Integer'), :value('1'), :node($/) ); }
if $<init> { my $init := $( $<init>[0] ); $past.unshift($init); } if $<step> { my $step := $( $<step>[0] ); $body := PAST::Stmts.new( $body, $step, :node($/) ); } my $loop := PAST::Op.new( $cond, $body, :pasttype('while'), :node($/) ); $past.push($loop); make $past; }
method for2_statement($/) { my $past := PAST::Block.new( :blocktype('immediate'), :node($/) ); my $loop := PAST::Op.new( :pasttype('while'), :node($/) );
$past.push( $( $<declaration> ) ); my $body := $( $<statement> ); if $<step> { my $step := $( $<step>[0] ); } my $cond; if $<cond> { $cond := $( $<cond>[0] ); } else { $cond := PAST::Val.new( :returns('Integer'), :value('1'), :node($/) ); } $loop.push($cond); $loop.push($body); $past.push($loop); make $past; }
method expression($/) { if +$<assignment_expression> != 1 { my $past := PAST::Stmts.new( :node($/) ); for $<assignment_expression> { $past.push( $( $_ ) ); } make $past; } else { make $( $<assignment_expression>[0] ); } }
method expression_statement($/) { if $<expression> { make $( $<expression>[0] ); } else { make PAST::Op.new( :inline(' # empty statement'), :node($/) ); } }
method compound_statement($/) { my $past := PAST::Block.new( :blocktype('immediate'), :node($/) ); #my $past := PAST::Stmts.new( :node($/) ); for $<block_item> { $past.push( $($_) ); } make $past; }
method if_statement($/) { my $cond := $( $<expression> ); my $then := $( $<statement> ); my $past := PAST::Op.new( $cond, $then, :pasttype('if'), :node($/) ); if $<else> { $past.push( $( $<else>[0] ) ); } make $past; }
method do_while_statement($/) { my $cond := $( $<expression> ); my $body := $( $<statement> ); make PAST::Op.new( $cond, $body, :pasttype('repeat_while'), :node($/) ); }
method while_statement($/) { my $cond := $( $<expression> ); my $body := $( $<statement> ); make PAST::Op.new( $cond, $body, :pasttype('while'), :node($/) ); }
method block_item($/, $key) { make $( $/{$key} ); }
method constant($/, $key) { make $( $/{$key} ); }
method constant_expression($/) { make $( $<conditional_expression> ); }
method assignment_expression($/) { make $( $<conditional_expression> ); }
method conditional_expression($/) { my $cond := $( $<logical_expression> ); if $<expression> { my $then := $( $<expression>[0] ); my $else := $( $<conditional_expression>[0] ); make PAST::Op.new( $cond, $then, $else, :pasttype('if'), :node($/) ); } else { make $cond; } }
method postfix_expression_prefix($/, $key) { make $( $/{$key} ); }
method postfix_expression_suffix($/, $key) { make $( $/{$key} ); }
method index($/) { my $expr := $( $<expression> ); ## XXX make PAST::Op.new( $expr, :name('xxx_index'), :pasttype('call'), :node($/) ); }
method direct_field($/) { my $field := $( $<identifier> ); ## XXX make PAST::Op.new( $field, :name('xxx_get_field'), :pasttype('call'), :node($/) ); }
method indirect_field($/) { my $field := $( $<identifier> ); ## XXX make PAST::Op.new( $field, :name('xxx_get_indirect'), :pasttype('call'), :node($/) ); }
method inc_or_dec($/) { my $opname := 'postfix:' ~ ~$<op>; my $past := PAST::Op.new( :name($opname), :pasttype('call'), :node($/) ); make $past; }
method arguments($/) { if $<argument_expression_list> { make $( $<argument_expression_list>[0] ); } else { make PAST::Op.new( :pasttype('call'), :node($/) ); } }
method argument_expression_list($/) { my $past := PAST::Op.new( :pasttype('call'), :node($/) ); for $<assignment_expression> { $past.push( $( $_ ) ); } make $past; }
method postfix_expression($/) { my $past := $( $<postfix_expression_prefix> ); for $<postfix_expression_suffix> { ## XXX my $args := $( $_ ); $args.unshift($past); $past := $args; } make $past; }
method prefix_expression($/) { my $opname := 'prefix:' ~ ~$<op>; my $expr := $( $<unary_expression> ); make PAST::Op.new( $expr, :name($opname), :pasttype('call'), :node($/) ); }
method primary_expression($/, $key) { make $( $/{$key} ); }
method unary_expression($/, $key) { make $( $/{$key} ); }
method integer_constant($/) { make PAST::Val.new( :value( ~$/ ), :returns('Integer'), :node($/) ); }
method floating_constant($/) { make PAST::Val.new( :value( ~$/ ), :returns('Float'), :node($/) ); }
method c_string_literal($/) { make PAST::Val.new( :value( ~$<string_literal> ), :node($/) ); #make PAST::Val.new( :value( ~$/ ), :node($/) ); }
method identifier($/) { ## XXX fix scopes ## XXX fix declarations so that :viviself can be removed make PAST::Var.new( :name( ~$/ ), :scope('package'), :viviself('Integer'), :node($/) ); }
method cast_expression($/) { make $( $<unary_expression> ); }
method logical_expression($/, $key) { if ($key eq 'end') { make $($<expr>); } else { my $past := PAST::Op.new( :name($<type>), :pasttype($<top><pasttype>), :pirop($<top><pirop>), :lvalue($<top><lvalue>), :node($/) ); for @($/) { $past.push( $($_) ); } make $past; }
}
# Local Variables: # mode: cperl # cperl-indent-level: 4 # fill-column: 100 # End: # vim: expandtab shiftwidth=4: