From dc4fd265395e6f24cdd2afee750fc2306c7a51c0 Mon Sep 17 00:00:00 2001 From: Chris Dolan Date: Thu, 19 Feb 2009 23:55:52 -0600 Subject: [PATCH] Support namespacing with packages and inner classes --- lib/Perk/Grammar.pm | 13 ++++----- lib/Perk/Grammar/Actions.pm | 52 +++++++++++++++++++++++++++--------- t/com/example/Namespace.java | 10 +++++++ 3 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 t/com/example/Namespace.java diff --git a/lib/Perk/Grammar.pm b/lib/Perk/Grammar.pm index 25d2e5a..8a81a0d 100644 --- a/lib/Perk/Grammar.pm +++ b/lib/Perk/Grammar.pm @@ -65,7 +65,7 @@ rule compilationUnit { } rule packageDeclaration { - 'package' ';' + 'package' $=[] ';' {*} } rule importDeclaration { @@ -109,8 +109,9 @@ rule normalClassDeclaration { 'class' ? ['extends' ]? ['implements' ]? - - {*} + {*} #= start + + {*} #= end } rule typeParameters { @@ -175,7 +176,7 @@ rule classBodyDeclaration { rule memberDecl { | {*} #= genericMethodOrConstructorDecl - | 'void' {*} #= voidMethodDeclaratorRest + | 'void' {*} #= voidMethodDeclaratorRest | {*} #= memberDeclaration | {*} #= constructorDeclaratorRest | {*} #= interfaceDeclaration @@ -233,7 +234,7 @@ rule methodDeclaratorRest { rule voidMethodDeclaratorRest { ['throws' ]? - [ | ';' ] + [ | ';' ] {*} } @@ -475,7 +476,7 @@ rule block { '{' * '}' {*} } -rule blockStatement { +rule blockStatement { | {*} #= localVariableDeclarationStatement | {*} #= classOrInterfaceDeclaration | {*} #= statement diff --git a/lib/Perk/Grammar/Actions.pm b/lib/Perk/Grammar/Actions.pm index d71a2bd..d066868 100644 --- a/lib/Perk/Grammar/Actions.pm +++ b/lib/Perk/Grammar/Actions.pm @@ -16,6 +16,9 @@ value of the comment is passed as the second argument to the method. class Perk::Grammar::Actions; +our @package; +our @classes; + method TOP($/) { make $( $ ); } @@ -36,7 +39,8 @@ method compilationUnit($/) { } method packageDeclaration($/) { - say('package'); + my $package = ~$; + @package = $package.split('.'); } method annotation($/) { @@ -99,17 +103,41 @@ method classDeclaration($/, $key) { make $( $/{$key} ); } -method normalClassDeclaration($/) { - my $class := $( $ ); - $class.loadinit().push( - PAST::Op.new( - :pasttype('call'), - :name('!create_class'), - ~$ - ) - ); - $class.namespace(~$); - make $class; +method normalClassDeclaration($/, $key) { + if $key eq 'start' { + my @ns = self._compute_local_ns(~$); + @classes.push(@ns.join('.')); + } else { + @classes.pop; + my @ns = self._compute_local_ns(~$); + my $classname = @ns.join('.'); + my $class := $( $ ); + $class.loadinit().push( + PAST::Op.new( + :pasttype('call'), + :name('!create_class'), + $classname + ) + ); + $class.namespace(@ns); + make $class; + } +} +method _compute_local_ns(Str $name) { + my @ns; + if $name ~~ m/\./ { + # Fully qualified class + @ns = $name.split('.'); + } elsif @classes.elems > 0 { + # Inner class + @ns = @classes[*-1].split('.'); + @ns.push($name); + } else { + # Prepend package + @ns = @package; + @ns.push($name); + } + return @ns; } method classBody($/) { diff --git a/t/com/example/Namespace.java b/t/com/example/Namespace.java new file mode 100644 index 0000000..db5c85a --- /dev/null +++ b/t/com/example/Namespace.java @@ -0,0 +1,10 @@ +package com.example; + +public class Namespace { + + class Inner { + } + + public static void main(String[] args) { + } +}