Another PHP indeter to be tested
authorHarvie <tomas@mudrunka.cz>
Mon, 1 Nov 2010 16:14:08 +0000 (17:14 +0100)
committerHarvie <tomas@mudrunka.cz>
Mon, 1 Nov 2010 16:14:08 +0000 (17:14 +0100)
scripts/phpindent.pl [new file with mode: 0755]

diff --git a/scripts/phpindent.pl b/scripts/phpindent.pl
new file mode 100755 (executable)
index 0000000..6cb145c
--- /dev/null
@@ -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 <squat@riot.org>
+#          Peter Palfrader <peter@palfrader.org>
+#
+#     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 => "<?\n" . $item[2]->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:
This page took 0.247627 seconds and 4 git commands to generate.