Jakiś przyzwoity parser PHP napisany w PHP? [Zamknięte]

80

Wykonuję dużo pracy, manipulując i analizując kod PHP. Zwykle używam do tego Tokenizera . W większości zastosowań jest to wystarczające. Ale czasami parsowanie przy użyciu leksera po prostu nie jest wystarczająco niezawodne (oczywiście).

Dlatego szukam parsera PHP napisanego w PHP. Znalazłem hnw / PhpParser i kumatch / stagehand-php-parser . Oba są tworzone przez automatyczną konwersję zend_language_parser.y do pliku .y z PHP zamiast C (a następnie skompilowane do parsera LALR (1)). Ale z tą automatyczną konwersją po prostu nie można pracować.

Czy jest jakiś przyzwoity parser PHP napisany w PHP? (Potrzebuję jednego dla PHP 5.2 i jednego dla 5.3. Ale tylko jeden z nich też byłby dobrym punktem wyjścia).

NikiC
źródło
1
Jaki jest Twój cel? Co próbujesz tutaj osiągnąć?
Charles,
3
@Charles: Jest wiele rzeczy, do których mógłbym to wykorzystać. Po prostu wszystko, co wymaga kodu źródłowego PHP w reprezentacji AST;)
NikiC
1
@mario: To daje dużo informacji. Tak naprawdę jest przeznaczony tylko do wyodrębnienia niektórych informacji o pliku. Więc zachowuje tylko takie rzeczy, jak instrukcje klas, instrukcje metod lub instrukcje powrotu, ale ignoruje wszystko, co mnie najbardziej interesuje: kod.
NikiC,
2
Nie sądzę, abyś znalazł jakieś solidne parsery języka na dużą skalę zakodowane w PHP. Po prostu nie ma potrzeby.
Ira Baxter,
4
W ciągu ostatniego tygodnia samodzielnie napisałem wstępną wersję parsera: github.com/nikic/PHP-Parser Przetestowałem ją na mojej bazie kodu i działała dobrze. Będę pracował nad ulepszeniem interfejsów, aby były faktycznie użyteczne.
NikiC

Odpowiedzi:

128

Ponieważ nie znaleziono tu kompletnego i stabilnego parsera, zdecydowałem się napisać go samodzielnie. Oto wynik:

PHP-Parser : parser PHP napisany w PHP

Projekt obsługuje parsowanie kodu napisanego dla dowolnej wersji PHP od PHP 5.2 do PHP 7.1.

Oprócz samego parsera biblioteka zawiera kilka powiązanych komponentów:

  • Kompilacja AST z powrotem do PHP („ładne drukowanie”)
  • Infrastruktura do przejeżdżania i zmiany AST
  • Serializacja do iz XML (a także zrzucanie w postaci czytelnej dla człowieka)
  • Rozpoznawanie nazw w przestrzeni nazw (aliasy itp.)

Przegląd użycia można znaleźć w sekcji „Użycie podstawowych składników” w dokumentacji .

NikiC
źródło
2
To jest niesamowite! Czy masz plan, aby to utrzymać?
MikeSchinkel
1
@NikiC Dzięki stary! To świetna biblioteka :-)
BVengerov,
1
Wow, obsługa PHP 7.1 na początku grudnia 2011 roku!
dotancohen
9

To nie będzie dla ciebie świetna opcja, ponieważ narusza ograniczenie czystego PHP, ale:

Jakiś czas temu ludzie z php-internals zdecydowali, że przejdą na Lemon jako technologię parsowania. W repozytorium svn PHP znajduje się gałąź, która zawiera wymagane zmiany.

Postanowili nie kontynuować tego , ponieważ stwierdzili, że ich roztwór Lemon jest o około 10-15% wolniejszy. Ale gałąź wciąż tam jest.

Istnieje starszy parser Lemon napisany jako rozszerzenie PHP. Możesz z tym pracować. Jest też ten pakiet PEAR . Jest też ta inna paczka z cytryną (za pośrednictwem tego wpisu na blogu o PGN ).

Oczywiście, nawet jeśli sprawisz, że to zadziała, nie jestem pewien, co zrobiłbyś z danymi, ani jak one w ogóle wyglądają.

Inną zwariowaną opcją byłoby zajrzenie do Quercus , implementacji PHP w Javie. Musieliby napisać parser, może warto to zbadać.

Charles
źródło
Po pierwsze: +1 do obszernych badań. Głównym problemem nie jest to, że nie ma możliwości zbudowania parsera w PHP. Wspomniałeś już o używaniu gramatyki Lemon PHP i jej kompilowaniu. Jeszcze łatwiej byłoby prawdopodobnie użyć "prawdziwej" gramatyki yacc / bison (są też kompilatory do tego). Problem polega na tym, że przekształcenie kodu yacc C do generowania instrukcji w kod yacc PHP do generowania AST wymaga naprawdę dużo pracy. Więc szukałem, czy ktoś już to zrobił.
NikiC
@nikic Jednym z powodów, IMO, dla których nikt jeszcze tego nie zrobił, jest brak specyfikacji tego, czym naprawdę jest PHP i jak go przeanalizować. php-internals wcześniej odrzucił całą koncepcję. W rezultacie poza samym kodem źródłowym PHP nie ma autorytatywnego źródła, w jaki sposób przeprowadzić analizę. Bez tego wiarygodnego źródła do odniesienia, zbudowanie poprawnego parsera będzie prawdziwą przygodą. To niestety oznacza, że ​​rozpoczęcie od danych yacc lub Lemon może być najlepszą opcją.
Charles
@nikic, Charles: To była prawdziwa przygoda dla naszego parsera PHP. Podejście: zaproponuj lekser / gramatykę, wypróbuj tysiące plików, pomyl się, dostosuj, spróbuj ponownie. Uzyskanie solidnego parsera dla słabo udokumentowanego języka zajmuje około roku. Przynajmniej zrobiło to dla nas. YMMV, ale prawdopodobnie niewiele.
Ira Baxter
7

Narzędzie pomiarowe PHP Depend zawiera kod do generowania AST ze źródła PHP napisanego w całości w języku PHP. Jednak korzysta z własnego token_get_all PHP do tokenizacji.

Kod źródłowy jest dostępny na github: https://github.com/manuelpichler/pdepend/tree/master/src/main/php/PHP/Depend

Implementacja AST dla niektórych części, takich jak wyrażenia matematyczne, nie była jeszcze zakończona, kiedy ostatnio sprawdzałem, ale według jego autora jest to cel.

naderman
źródło
Ma AST, ale nie dla „operacji matematycznych” (zakładam, że masz na myśli „wyrażenia”? To kluczowa część langauge, zwłaszcza jeśli weźmiesz pod uwagę, że „literały ciągów znaków” w podwójnych cudzysłowach (z osadzonymi wyrażeniami) są naprawdę złożone wyrażenia łańcuchowe
Ira Baxter
2
Dostałeś nagrodę, bo to najbliższa odpowiedź na pytanie. Ale oczywiście nie jest to naprawdę użyteczne, ponieważ brakuje mu, cóż, połowy gramatyki PHP ...
NikiC
Treść tego posta jest nieaktualna. Od tego czasu rozwija się aktywnie, chociaż nie wiem, jak dobrze obsługuje gramatykę PHP.
nhahtdh
4

Cóż, to nie jest w PHP, przepraszam, ale budowanie tego rodzaju maszyn jest trudne, a PHP nie jest szczególnie przystosowane do przetwarzania języka.

Nasz PHP Front End to zapewnia pełną 4.x PHP 5.x (EDIT 9/2016: teraz obsługuje PHP 7) analizowania, automatycznie buduje ASTs ze wszystkimi szczegółami pełnej gramatyki PHP, może generować compilable tekst źródłowy z ASTs. Jest to trudniejsze, niż mogłoby się wydawać, biorąc pod uwagę wszystkie skomplikowane szczegóły, w tym dziwne literały ciągów, przechwycone komentarze, liczby z podstawą itp.

Ale AST to za mało (zauważyłeś już, że tokeny nie są nawet wystarczające).

Podstawa, na której jest zbudowany, DMS Software Reengineering Toolkit zapewnia wsparcie dla analizy i arbitralnych przekształceń AST. Odczytuje również duże zestawy plików naraz, umożliwiając analizę i transformacje w plikach PHP.

Ira Baxter
źródło
1
Tak jak odpowiedź na pierwsze zdanie: istnieją już generatory parserów, które mogą generować parser z gramatyki yacc (np. Kmyacc). To znaczy, że nie ma dużej różnicy między budowaniem go w PHP a budowaniem w jakimkolwiek innym języku. Wszystko, co musisz zrobić, to "po prostu" (ironia) zastąpić kod C w zend_language_parser.y jakimś kodem PHP, który tworzy drzewo węzłów.
NikiC
A co do reszty: naprawdę chciałbym mieć rozwiązanie PHP. Ale jeśli (i wydaje się to bardzo prawdopodobne) nie ma czegoś takiego, prawdopodobnie użyję czegoś innego. Słyszałem już kilka razy o DMS tutaj na SO, przyjrzę się temu.
NikiC
@ninkic: Wszystkie maszyny Turinga (w tym PHP) mogą symulować wszystkie inne maszyny Turinga, tak, oczywiście, można je zbudować w PHP. Ale a) buduje się tylko parser; Myślę, że parser PHP nie jest przeznaczony do budowania drzewa, ale raczej do zasilania generatora p-kodu PHP i myślę, że zauważysz, że potrzeby są inne, oraz b) ludzie wielokrotnie popełniają błąd zakładając, że jeśli mają AST, wszystko inne jest łatwe; popełniają ten błąd głównie dlatego, że nie mają doświadczenia w robieniu skomplikowanych rzeczy z AST. Zbudowałem DMS, ponieważ to założenie jest fałszywe.
Ira Baxter
1
a) Tak, parser PHP nie jest przeznaczony do budowania drzewa parsowania, jest przeznaczony do tworzenia strumienia kodu operacyjnego. Dlatego jest prawie niemożliwe automatyczne przekonwertowanie parsera języka zend na PHP. b) Prawdopodobnie jestem jednym z tych, którzy popełniają ten błąd;) Z faktu, że za pomocą czystego strumienia tokenów można już wykonać mnóstwo skomplikowanych manipulacji, wywnioskowałem (w twoich oczach błędnie?), że z AST byłoby to łatwiejsze bardziej stabilny.
NikiC
@nikic: Lekcja z 50 lat technologii kompilatorów jest taka, że ​​każda reprezentacja programu ułatwia pewne rzeczy. Państwo może zrobić jakiś program maninpulation się tylko na tekście. Możesz zrobić więcej na tokenach. Możesz zrobić jeszcze więcej na AST. Możesz robić naprawdę interesujące rzeczy, jeśli masz tabele symboli, informacje o sterowaniu i przepływie danych (wykresy), dane aliasingu zmiennych (analiza punktów do analizy). Kiedy próbujesz generować wyrafinowany kod, odkrywasz, że to wszystko jest naprawdę bardzo przydatne.
Ira Baxter