Commits

Toby Inkster  committed 9cce724

Parse import and package statements.

  • Participants
  • Parent commits 34279cc

Comments (0)

Files changed (3)

File examples/inferface-parsing.pl

 use Data::Dumper;
 
 my $doc = Java::Parser->new(tokens => <<'JAVA')->parse;
+package uk.co.tobyinkster;
+
+import java.lang.*;
+import uk.org.buzzword.*;
+
 /**
  * interface Predator
  */
 JAVA
 
 print "use 5.010;\n";
-print "use MooseX::Declare;\n\n";
+print "use MooseX::Declare;\n";
+foreach my $import (@{ $doc->imports })
+{
+	printf("use Java::import '%s';\n", $import->name);
+}
+print "\n";
 
 foreach my $decl (@{ $doc->declarations })
 {
 	push @code, map
 		{ sprintf("requires '%s'; # returns %s", $_->name, $_->type); }
 		@{ $decl->methods };
-	
-	my $code = sprintf("role %s\n", $decl->name)
-		. (join q{}, map {"\twith $_\n"} @{ $decl->base })
+
+	my $code = sprintf("role %s\n", $doc->perl_qualified_name($decl->name))
+		. (join q{},
+			map {"\twith $_\n"}
+			map {$doc->perl_qualified_name($_)}
+			@{ $decl->base })
 		. "{\n"
 		. (join q{}, map {"\t$_\n"} @code)
 		. "}\n\n";

File lib/Java/Parser.pm

 		#p($self->tokens);
 		
 		$self->eat_cruft;
+
+		if ($self->next_token_matches('.Keyword', 'package'))
+		{
+			$doc->package($self->parse_package);
+			$self->eat_cruft;
+		}
+
+		while ($self->next_token_matches('.Keyword', 'import'))
+		{
+			$doc->push_import($self->parse_import_statement);
+			$self->eat_cruft;
+		}
+
 		while ($self->count_tokens)
 		{
 			$doc->push_declaration(
 		$doc;
 	}
 	
+	method parse_dotted_name
+	{
+		$self->eat_cruft;
+		
+		my @bits;
+		BIT: while (1)
+		{
+			if ($self->next_token_matches('.Identifier')
+			||  $self->next_token_matches('.Keyword'))
+			{
+				push @bits, $self->eat_token;
+				$self->eat_cruft;
+				
+				if ($self->next_token_matches('.Semicolon'))
+				{
+					$self->eat_token;
+					$self->eat_cruft;
+					last BIT;
+				}
+				elsif ($self->next_token_matches('.Op.Dot'))
+				{
+					$self->eat_token;
+					$self->eat_cruft;
+					next BIT;
+				}
+				else
+				{
+					confess "that I haven't got anything to do here.";
+				}
+			}
+		}
+		
+		join '.', map { $_->spelling } @bits;
+	}
+	
+	method parse_import_statement
+	{
+		$self->eat_cruft;
+		my $toke = $self->eat_token('.Keyword', 'import');
+		$self->eat_cruft;		
+		my @modifiers = $self->parse_modifiers;
+		$self->eat_cruft;
+		return Java::Ast::Statement::Import->new(
+			token     => $toke,
+			name      => $self->parse_dotted_name,
+			modifiers => \@modifiers,
+			);
+	}
+	
+	method parse_package
+	{
+		$self->eat_cruft;
+		my $toke = $self->eat_token('.Keyword', 'package');
+		$self->eat_cruft;
+		$self->parse_dotted_name;
+	}
+	
 	method parse_modifiers
 	{
 		my @modifiers;
 		if ($self->next_token_matches('.Keyword', 'if'))
 			{ return $self->parse_if_statement }
 
-		if ($self->next_token_matches('.Keyword', 'import'))
-			{ return $self->parse_import_statement }
-
-		if ($self->next_token_matches('.Keyword', 'package'))
-			{ return $self->parse_package_statement }
-
 		if ($self->next_token_matches('.Keyword', 'return'))
 			{ return $self->parse_return_statement }
 
 
 class Java::Ast::Document
 	extends Java::Ast
-	with Java::Ast::WithDeclarations;
+	with Java::Ast::WithDeclarations
+{
+	has 'package' => (
+		is       => 'rw',
+		isa      => 'Str',
+		);
+
+	has imports => (
+		is       => 'rw',
+		isa      => 'ArrayRef[Java::Ast::Statement::Import]',
+		traits   => [qw/Array/],
+		default  => sub { [] },
+		handles  => { push_import => 'push' },
+		);
+	
+	method qualified_name (Str $name)
+	{
+		return $name unless length $self->package;
+		join '.', ($self->package, $name);
+	}
+	
+	method perl_qualified_name (Str $name)
+	{
+		my $qname = join '.', ('Java', 'lib', $self->qualified_name($name));
+		$qname =~ s{\.}{::}g;
+		return $qname;
+	}
+}
 
 class Java::Ast::TypeDeclaration
 	extends Java::Ast
 class Java::Ast::Statement
 	extends Java::Ast;
 
+class Java::Ast::Statement::Import
+	extends Java::Ast::Statement
+	with Java::Ast::WithModifiers
+{
+	has name => (
+		is       => 'rw',
+		isa      => 'Str',
+		);
+}
+
 class Java::Ast::Statement::Expression
-	extends Java::Ast
+	extends Java::Ast::Statement
 {
 	has expression => (
 		is       => 'rw',
 }
 
 class Java::Ast::Statement::Return
-	extends Java::Ast
+	extends Java::Ast::Statement
 {
 	has expression => (
 		is       => 'rw',

File lib/Java/Tokeniser.pm

 {
 	method tokenise
 	{
-		my $count = 0;
-		my $op_state = 0;
+		my $count     = 0;
+		my $op_state  = 0;
+		my $in_import = 0;
 		
 		while ($self->not_finished)
 		{
 			
 			if ($self->peek_stream($self->keywords_regexp))
 			{
+				$in_import = ($self->last_match eq 'import');
 				$self->eat_stream($self->last_match);
 				$self->push_token_from_match($self->keywords_class);
 			}
 			}
 			elsif ($self->peek_stream($self->semicolon_regexp))
 			{
+				$in_import = 0;
 				$self->eat_stream($self->last_match);
 				$self->push_token_from_match($self->semicolon_class);
 			}
 			}
 			elsif ($self->peek_stream($self->operator_regexp))
 			{
-				$self->eat_stream($self->last_match);
-				$self->push_token_from_match($self->operator_class($self->last_match, $op_state));
+				if ($self->last_match eq '*'
+				and $in_import)
+				{
+					$self->eat_stream($self->last_match);
+					$self->push_token_from_match($self->keywords_class);
+				}
+				else
+				{
+					$self->eat_stream($self->last_match);
+					$self->push_token_from_match($self->operator_class($self->last_match, $op_state));
+				}
 			}
 			elsif ($self->peek_stream($self->literal_integer_binary_regexp))
 			{