From: Harvie Date: Mon, 1 Nov 2010 16:14:08 +0000 (+0100) Subject: Another PHP indeter to be tested X-Git-Url: https://git.harvie.cz/?a=commitdiff_plain;h=a6540423d767fef5806cbf50bd06f476620c6e1d;p=mirrors%2FKyberia-bloodline.git Another PHP indeter to be tested --- diff --git a/scripts/phpindent.pl b/scripts/phpindent.pl new file mode 100755 index 0000000..6cb145c --- /dev/null +++ b/scripts/phpindent.pl @@ -0,0 +1,552 @@ +#!/usr/bin/perl -w + +# php indenter +# Reformats your php source code +# +# $Id: phpindent,v 1.1 2002/05/20 12:54:03 weasel Exp $ +# +# +# Depends: Parse::RecDescent +# +# +# (c) 2002 Florian Reitmeir +# Peter Palfrader +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# +# Usage: phpindent < orig.php > new.php +# +# +# - It might corrupt your code +# - It might not even work at all +# - It does not understand all of php +# - It's damn slow (several hours for one of our 800 line examples on a gHz +# CPU) +# - But it was fun to write and merely to test out Parse::RecDescent +# +# It was just a proof of concept - don't use it in production +# +# Did I mention it was slow? +# +# +# Q: So why did you write it? +# A: It was an ad hoc quick hack which went out of control but was +# real fun. +# +# Q: So are there any real php indenters? +# A: We didn't find any which is why we tried this nonsense at all. +# If you find any just let us know and we will link to them. +# +# Q: Will you improve this indenter/fix bugs I report? +# A: Probably not. But if you happen to have lots of time we would +# welcome a patch or two. +# +# Q: You know your grammar sucks? +# A: yepp. +# + +####################################################################### +package MyToken; + +sub new +{ + my ($class, %args) = @_; + bless \%args, $class; +} + +####################################################################### +package MyBinaryOperator; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self) = @_; + return + sprintf "%s %s %s", + $self->{left}->reprint(), + $self->{'operator'}, + $self->{right}->reprint(); +}; + +####################################################################### +package MyPostOperator; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self) = @_; + return + sprintf "%s %s", + $self->{left}->reprint(), + $self->{'operator'}; +}; + +####################################################################### +package MyPreOperator; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self) = @_; + return + sprintf "%s %s", + $self->{'operator'}, + $self->{right}->reprint(); +}; + +####################################################################### +package MyAtom; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self) = @_; + + return + sprintf "%s", + $self->{'value'}; +}; + +####################################################################### +package MyStatement; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self) = @_; + + return + sprintf "%s;\n", + $self->{'value'}; +}; + +####################################################################### +package MyComment; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'} || 1; + my $i = "\t" x ($il -1 ); + + my $value = $self->{'value'}; + $value =~ s,#\s*,# ,; + $value =~ s,//\s*,\n\n$i// ,; + return + $value."\n"; +}; + +####################################################################### +package MyCommentMultiLine; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'}-1 || 0; + my $i = "\t" x $il; + + my $value = $self->{'value'}; + $value =~ s,/\*\s*\n?,,; + $value =~ s,\n?\s*\*/,,; + my @lines = map { s/^\s*\*?[ \t]*/$i * /; $_ } split /\n/, $value; + unshift @lines, "/*"; + push @lines, "$i */"; + + return + sprintf "%s\n", + join ("\n", @lines) +}; + +####################################################################### +package MyCommentDoc; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'}-1 || 0; + my $i = "\t" x $il; + + my $value = $self->{'value'}; + $value =~ s,^/\*\*[ \t]*\n?,,; + $value =~ s,\n?[ \t]*\*/$,,; + $value =~ s/\t/ /g; + my @lines = split /\n/, $value; + + my $maxwhitespace; + for (@lines) { + my ($leadwhitespace) = ($_ =~ /^(\s*)/); + $maxwhitespace = (!defined ($maxwhitespace) || length($leadwhitespace) < $maxwhitespace) ? + length($leadwhitespace) : + $maxwhitespace; + }; + my $leadwhitespace = " " x $maxwhitespace; + @lines = map { s/^$leadwhitespace//; s/^/$i /; $_ } @lines; + + unshift @lines, "/**"; + push @lines, "$i */"; + + return + sprintf "%s\n", + join ("\n", @lines) +}; + +####################################################################### +package MyConditionalBlock; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'} || 0; + my $i = "\t" x $il; + + my $block = $self->{block}->reprint(indent => $il, noend=>1); + if ($block =~ /^\s*\{/) { + $block = "\t" x ($il-1) . $block; + $isblock = 1; + } else { + $block = "\t" x ($il) . $block; + $isblock = 0; + }; + + + my $elseblock; + if ($self->{type} eq 'ifelse') { + $elseblock = $self->{elseblock}->reprint(indent => $il, noend=>1); + if ($elseblock =~ /^\s*\{/) { + $elseblock = "\t" x ($il-1) . $elseblock; + $elseisblock = 1; + } else { + $elseblock = "\t" x ($il) . $elseblock; + $elseisblock = 0; + }; + }; + + if ($self->{type} eq 'if' || $self->{type} eq 'while') { + return + $self->{type}. + " (". + $self->{condition}->reprint(). + ")\n". + $block. + ($isblock ? ";\n" : ""); + } elsif ($self->{type} eq 'ifelse') { + return + "if". + " (". + $self->{condition}->reprint(). + ")\n". + $block. + ($elseisblock ? "\n" : ""). + "\t"x($il-1) . "else\n". + $elseblock. + ($elseisblock ? ";\n" : ""); + } elsif ($self->{type} eq 'dowhile') { + return + "do\n". + $block. + " while (". + $self->{condition}->reprint(). + ");\n"; + } elsif ($self->{type} eq 'for') { + return + $self->{type}. + " (". + $self->{part1}->reprint(). + "; ". + $self->{part2}->reprint(). + "; ". + $self->{part3}->reprint(). + ")\n". + $block. + ($isblock ? ";\n" : ""); + } elsif ($self->{type} eq 'foreach') { + return + $self->{type}. + " (". + $self->{part1}->reprint(). + " as ". + $self->{part2}->reprint(). + ")\n". + $block. + ($isblock ? ";\n" : ""); + }; + +}; + +####################################################################### +package MyParam; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'} || 1; + my $i = "\t" x $il; + + my $statements = join (", ", map { $_->reprint() } @{$self->{'statements'}}); + + return + $statements; +}; + +####################################################################### +package MyFunction; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'} || 1; + my $i = "\t" x $il; + + return + $self->{name}->reprint(). + " (". + ((defined $self->{params}) ? $self->{params}->reprint() : ""). + ")"; +}; + +####################################################################### +package MyBlock; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + my $il = $args{'indent'} || 1; + my $i = "\t" x $il; + + my $statements = join ($i, map { $_->reprint(indent => $il + 1) } @{$self->{'statements'}}); + + $statements = $i.$statements if ( substr($statements,0,1) ne "\n" ); + + return + ((defined $args{'nobraces'}) ? "" : "{\n"). + $statements. + "\t" x ($il-1). + ((defined $args{'nobraces'}) ? "" : "}"). + ((defined $args{'noend'}) ? "" : ";\n"); +}; + +####################################################################### +package MyFunctionDefinition; +@ISA = qw( MyToken ); + +sub reprint +{ + my ($self, %args) = @_; + + my $il = $args{'indent'} || 1; + my $i = "\t" x ($il-1); + + return + "\n". + $i."function ". + $self->{'header'}->reprint(). "\n". + $i.$self->{'block'}->reprint(indent => $il)."\n"; +}; + + + + +####################################################################### +package main; + +use strict; +use Parse::RecDescent; + + +my $input; +local $/ = undef; +$input = <>; + +my $grammar = q +{ + Script: /<\?(php)?/ Block '?>' { MyAtom->new ( value => "reprint(nobraces=>1) ."?>\n" ) } + + GroupedBlock: '{' Block '}' /;?/ { MyBlock->new ( statements => [ @{$item[2]->{'statements'}} ] ) } + + Block: Statement Block { MyBlock->new ( statements => [ $item[1], @{$item[2]->{'statements'}} ] ) } + | Statement { MyBlock->new ( statements => [ $item[1] ] ) } + + Statement: Expression ';' { MyStatement->new ( value => $item[1]->reprint() ) } + | ';' { MyStatement->new ( value => '' ) } + | GroupedBlock ';' { $item[1] } + | GroupedBlock + | Comment + | IfThenElseBlock + | IfBlock + | WhileBlock + | DoWhileBlock + | ForLoop + | ForEachLoop + | FunctionDefinition + + FunctionDefinition: "function" FunctionCall GroupedBlock + { MyFunctionDefinition->new ( header => $item[2], block => $item[3] ) } + + + IfThenElseBlock: "if" "(" Expression ")" Statement "else" Statement + { MyConditionalBlock->new ( type => 'ifelse', + condition => $item[3], + block => $item[5], + elseblock => $item[7] ) } + IfBlock: "if" "(" Expression ")" Statement + { MyConditionalBlock->new ( type => 'if', + condition => $item[3], + block => $item[5] ) } + WhileBlock: "while" "(" Expression ")" Statement + { MyConditionalBlock->new ( type => 'while', + condition => $item[3], + block => $item[5] ) } + DoWhileBlock: "do" GroupedBlock "while" "(" Expression ")" ";" + { MyConditionalBlock->new ( type => 'dowhile', + condition => $item[5], + block => $item[2] ) } + ForLoop: "for" "(" Expression ";" Expression ";" Expression ")" Statement + { MyConditionalBlock->new ( type => 'for', + part1 => $item[3], + part2 => $item[5], + part3 => $item[7], + block => $item[9] ) } + ForEachLoop: "foreach" "(" Expression "as" Expression ")" Statement + { MyConditionalBlock->new ( type => 'foreach', + part1 => $item[3], + part2 => $item[5], + block => $item[7] ) } + Expression: "(" Expression ")" { $item[2] } + | FunctionCall Operator Expression + { MyBinaryOperator->new ( left=>$item[1], operator=>$item[2], right=>$item[3] ) } + | Atom Operator Expression + { MyBinaryOperator->new ( left=>$item[1], operator=>$item[2], right=>$item[3] ) } + | Atom Operator { MyPostOperator->new ( left=>$item[1], operator=>$item[2] ) } + | PreOperator Expression { MyPreOperator->new ( right=>$item[2], operator=>$item[1] ) } + | FunctionCall + | Atom + + + Comment: CommentHash + | CommentSlash + | CommentDoc + | CommentMultiLine + + CommentHash: /#.*?$/m { MyComment->new ( value => $item[1] ) } + CommentSlash: /\/\/.*?$/m { MyComment->new ( value => $item[1] ) } + CommentDoc: /\/\*\*.*?\*\//s { MyCommentDoc->new ( value => $item[1] ) } + CommentMultiLine: /\/\*.*?\*\//s { MyCommentMultiLine->new ( value => $item[1] ) } + + Operator: '===' + | '!==' + | '+=' + | '-=' + | '==' + | '!=' + | '=>' + | '<=' + | '>=' + | '++' + | '--' + | '&&' + | '.=' + | '||' + | '&' + | '|' + | '>' + | '<' + | '=' + | '/' + | '+' + | '-' + | '*' + | '.' + | ':' + | '?' + + PreOperator: "new" + | "print" + | "return" + | "echo" + | "not" + | "++" + | "--" + | "-" + | "+" + | "1" + | "!" + + + + FunctionCall: Atom "(" FunctionParameter ")" + { MyFunction->new ( name => $item[1], params => $item[3] ) } + | Atom "(" ")" + { MyFunction->new ( name => $item[1] ) } + + Atom: Variable + | String + | Identifier + | Numerical + + + FunctionParameter: Expression "," FunctionParameter + { MyParam->new ( statements => [ $item[1], @{$item[3]->{'statements'}} ] ) } + | Expression { MyParam->new ( statements => [ $item[1] ] ) } + + + Variable: '$' Identifier Array + { MyAtom->new ( value => '$'.$item[2]->reprint() . $item[3]->reprint() ) } + | '$' Identifier { MyAtom->new ( value => '$'.$item[2]->reprint() ) } + + + Array: "[" "]" Array { MyAtom->new ( value => '[]'.$item[3]->reprint() ) } + | "[" Expression "]" Array + { MyAtom->new ( value => '['.$item[2]->reprint().']'.$item[4]->reprint() ) } + | "[" Expression "]" { MyAtom->new ( value => '['.$item[2]->reprint().']' ) } + | "[" "]" { MyAtom->new ( value => '[]' ) } + + + Identifier: SimpleIdentifier "->" Identifier + { MyAtom->new ( value => $item[1]->reprint() ."->" .$item[3]->reprint() ) } + | SimpleIdentifier + + SimpleIdentifier: /[a-zA-Z][a-zA-Z0-9_]*/ { MyAtom->new ( value => $item[1] ) } + + Numerical: /[\d]+(\.[\d+])?/ { MyAtom->new ( value => $item[1] ) } + + String: EmptyDQString + | NotEmptyDQString + | EmptySQString + | NotEmptySQString + NotEmptyDQString: /".*?[^\\\\]"/s { MyAtom->new ( value => $item[1] ) } + EmptyDQString: '""' { MyAtom->new ( value => '""' ) } + NotEmptySQString: /'.*?[^\\\\]'/s { MyAtom->new ( value => $item[1] ) } + EmptySQString: "''" { MyAtom->new ( value => "''" ) } +}; + +#$::RD_HINT = 1; +my $parser = new Parse::RecDescent ($grammar); +my $tree = $parser->Script($input); + +print $tree->reprint(); + + + +# vim:set ts=4: +# vim:set shiftwidth=4: