parrotcode: Untitled | |
Contents | Compilers |
class NCIGEN::Grammar::Actions;
our $decls := NCIGENAST::Decls.new(); our $NCIGENDEBUG :=0;
method TOP($/) { if $NCIGENDEBUG { _dumper($decls); } make $decls; }
sub parse_decl_specs($/, $ast) { if $/ { for $/ { $ast.attr( strip_spaces(~$_), 1, 1); } } }
sub typedef($/) { if $/ { for $/ { if ('typedef' eq strip_spaces(~$_) ) { return 1; } } } return 0; }
method declaration($/) { my $ast := NCIGENAST::VarDecl.new( :node($/) ); my $type := "";
#say("================================================================================================="); #_dumper($/); # make $decls; # return 1; my $decl_specs := $<declaration_specifiers><repeatable_declaration_specifiers>; if typedef($decl_specs) { $ast := NCIGENAST::TypeDef.new( :node($/) ); $type := "TypeDef"; } elsif $/<init_declarator><init_declarator><declarator><direct_declarator><declarator_suffix><declarator_suffix><parameter_type_list> { $ast := NCIGENAST::FuncDecl.new( :node($/) ); $type := "FuncDecl"; } # elsif $<declaration_specifiers><type_specifier><type> { # $ast := NCIGENAST::Struct.new( :node($/) ); # $type := "Struct"; # } else { $ast := NCIGENAST::VarDecl.new( :node($/) ); $type := "VarDecl"; } parse_decl_specs( $<declaration_specifiers><repeatable_declaration_specifiers>, $ast ); # TYPE settype($<declaration_specifiers><type_specifier>, $ast); if ($type eq "FuncDecl") { if (+$<init_declarator> != 1) { say("ERROR FuncDecl has more than one <init_declarator>"); } #assert(+$<init_declarator><declarator><direct_declarator><declarator_suffix> == 1); my $params := $<init_declarator><declarator><declarator><direct_declarator><declarator_suffix><parameter_type_list><parameter_type_list><parameter_list><parameter_declaration>; for $params { my $param := NCIGENAST::Param.new( :node( $_ ) ); settype($_<declaration_specifiers><type_specifier>, $param); my $param_ident := $_<declarator>; if $param_ident { setname( $_, $param ); } ispointer($_, $param); $ast.push( $param ); } my $declarator := $<init_declarator><declarator>; my $name := setname($declarator, $ast); $decls{ $name } := $ast; ispointer($declarator, $ast); #if $NCIGENDEBUG { _dumper($ast); } #say($name); } #elsif ($type eq "VarDecl") { #elsif $<init_declarator> { else { for $<init_declarator> { my $l_ast := $ast.clone(); my $name := setname($_, $l_ast); $decls{ $name } := $l_ast; ispointer($_, $l_ast); #if $NCIGENDEBUG { _dumper($l_ast); } #say($name); } } #else { # say("OPAQUE STRUCT OR UNTION"); # _dumper($/); #} make $decls; }
sub countpointer($/) { if $<pointer> { return countpointer($<pointer>) + 1; } else { return 0; } }
sub ispointer($/, $ast) { if $/ { if ($<declarator><pointer>) { $ast.pointer(1); $ast.pointer_cnt(countpointer($<declarator><pointer>)); } if ($<abstract_declarator><pointer>) { $ast.pointer(1); $ast.pointer_cnt(countpointer($<abstract_declarator><pointer>)); } }
my $lookup_ast := $ast; repeat { =begin comment if $lookup_ast.pointer() { $ast.pointer(1); my $pc := +$ast.pointer_cnt(); $pc++; $ast.pointer_cnt($pc); } =end comment if $lookup_ast.builtin_type() { $ast.primitive_type(~($lookup_ast.type())); return 1; } my $type_name := $lookup_ast.type(); my $lookup_ast_name := $lookup_ast.name(); #FIXME struct or union typedef if ($lookup_ast.name() eq $type_name) { return 1; } $lookup_ast := $decls{$type_name}; unless $lookup_ast { #say("Parent " ~~ $lookup_ast_name ~~ " " ~~ $type_name ~~ " not defined"); return 1; } if $lookup_ast.pointer() { $ast.pointer(1); my $pc := +$ast.pointer_cnt(); $pc := $pc + $lookup_ast.pointer_cnt(); $ast.pointer_cnt($pc); } } while (1); #_dumper($ast); }
sub settype($/, $ast) { if $/ { #is it a struct or union my $struct_or_union := strip_spaces(~$<type>); if $struct_or_union { my $ident := $<struct_or_union_specifier><identifier><identifier>; if $ident { $ident := strip_spaces($ident.text()); } else { $ident := $<struct_or_union_specifier><identifier>; if $ident { $ident := strip_spaces($ident.text()); } else { $ident := "anonymous_" ~~ $struct_or_union~~ "1"; } } $ast.type($ident); my $s_or_u := $<struct_or_union_specifier><struct_declaration>; if $s_or_u { my $su; if ($struct_or_union eq "struct" ) { $su := NCIGENAST::Struct.new( :node($/) ); } else { $su := NCIGENAST::Union.new( :node($/) ); } $su.name($ident); build_struct_or_union($s_or_u, $su); $ast.complex($su); } } else { $ast.type(strip_spaces(~$/)); # BUILTIN_TYPE if $<builtin_type> { $ast.builtin_type(1); } } } else { say("ERROR no type specifier"); } }
sub strip_spaces($_) { $_.replace(' ', ''); return $_; }
sub build_struct_or_union($/, $ast) { for $/ { my $smt := NCIGENAST::VarDecl.new( :node($_) ); settype( $_<specifier_qualifier_list><type_specifier>, $smt ); for $_<struct_declarator_list> { my $sm := $smt.clone(); my $declarator := $_<struct_declarator><declarator>; $sm.name(strip_spaces($declarator.text())); ispointer($declarator, $sm); $ast.push($sm); } } }
sub setname($/, $ast) { my $name_node := $<declarator><direct_declarator><declarator_prefix>; if $name_node { $ast.name( ~$name_node ); return ~$name_node; } else { say("ERROR node doesn't have <direct_declarator><declarator_prefix>"); _dumper($/); } }
# Local Variables: # mode: cperl # cperl-indent-level: 4 # fill-column: 100 # End: # vim: expandtab shiftwidth=4 syntax=perl6:
|