File: Symbol.pm

package info (click to toggle)
libppi-perl 0.903-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 840 kB
  • ctags: 429
  • sloc: perl: 5,551; makefile: 45
file content (112 lines) | stat: -rwxr-xr-x 2,857 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package PPI::Token::Symbol;

# A symbol

use strict;
use UNIVERSAL 'isa';
use base 'PPI::Token';

use vars qw{$VERSION};
BEGIN {
	$VERSION = '0.903';
}

sub _on_char {
	my $t = $_[1];

	# Suck in till the end of the symbol
	my $line = substr( $t->{line}, $t->{line_cursor} );
	if ( $line =~ /^([\w:']+)/ ) {
		$t->{token}->{content} .= $1;
		$t->{line_cursor} += length $1;
	}

	# Handle magic things
	my $content = $t->{token}->{content};	
	if ( $content eq '@_' or $content eq '$_' ) {
		$t->_set_token_class( 'Magic' );
		return $t->_finalize_token->_on_char( $t );
	}

	# Shortcut for a couple of things
	if ( $content eq '%::' ) {
		return $t->_finalize_token->_on_char( $t );
	}
	if ( $content eq '$::' ) {
		# May well be an alternate form of a Magic
		my $nextchar = substr( $t->{line}, $t->{line_cursor}, 1 );
		if ( $nextchar eq '|' ) {
			$t->{token}->{content} .= $nextchar;
			$t->{line_cursor}++;
			$t->_set_token_class( 'Magic' );
		}
		return $t->_finalize_token->_on_char( $t );
	}
	if ( $content =~ /^(?:\$|\@)\d+/ ) {
		$t->_set_token_class( 'Magic' );
		return $t->_finalize_token->_on_char( $t );
	}

	# Trim off anything we oversucked...
	$content =~ /^((?:\$|\@|\%|\&|\*)(?:\'|\::)?[^\W\d]\w*(?:(?:\'|\::)[^\W\d]\w*)*(?:::)?)/ or return undef;
	unless ( length $1 eq length $content ) {
		$t->{line_cursor} += length($1) - length($content);
		$t->{token}->{content} = $1;
	}

	$t->_finalize_token->_on_char( $t );
}

# Returns the normalised, canonical symbol.
# For example, converts '$ ::foo'bar::baz' to '$main::foo::bar::baz'
# However, this does not resolve the symbol
sub canonical {
	my $symbol = shift->content;
	$symbol =~ s/\s+//;
	$symbol =~ s/(?<=[\$\@\%\&\*])::/main::/;
	$symbol =~ s/\'/::/g;
	$symbol;
}

# Returns the actual symbol this token refers to.
# A token of '$foo' might actually be refering to '@foo' if there is
# a '[1]' after it. This method attempts to resolve these issues.
sub symbol {
	my $self = shift;
	my $symbol = $self->canonical;

	# Immediately return the cases where it can't be anything else
	my $type   = substr( $symbol, 0, 1 );
	return $symbol if $type eq '%';
	return $symbol if $type eq '&';

	# Unless the next significant Element is a structure, it's correct.
	my $after  = $self->snext_sibling;
	return $symbol unless isa( $after, 'PPI::Structure' );

	# Process the rest for cases where it might actually be somethign else
	my $braces = $after->braces;
	return $symbol unless defined $braces;
	if ( $type eq '$' ) {
		return substr( $symbol, 0, 1, '@' ) if $braces eq '[]';
		return substr( $symbol, 0, 1, '%' ) if $braces eq '{}';

	} elsif ( $type eq '@' ) {
		return substr( $symbol, 0, 1, '%' ) if $braces eq '{}';

	}

	$symbol;
}

sub raw_type {
	my $self = shift;
	substr( $self->content, 0, 1 );
}

sub symbol_type {
	my $self = shift;
	substr( $self->symbol, 0, 1 );
}

1;