Struttura annidata di analisi da facebook pfff - come decidere sul parser

0

Sto giocando da un po 'con la creazione di un piccolo progetto open source basato sull'output di Facebook pfff tool, che può analizzare più linguaggi di programmazione ed emettere un qualche tipo di AST unificato.

Ad esempio, dato un semplice file PHP come questo:

<?php

class FooBar {
    public function functionA(string $arg1)
    {
        $localVar = 1;
        print $undefinedVar;
        print $arg1;
    }

    ...

L'output dello strumento è simile al seguente:

[ClassDef(
   {c_type=ClassRegular(i_1); c_name=Name(("FooBar", i_2)); c_tparams=None;
    c_extends=None; c_implements=None; c_attrs=None;
    c_body=(i_3,
            [Method(
               {f_tok=i_4; f_type=MethodRegular; f_attrs=None;
                f_modifiers=[(Public, i_5)]; f_ref=None;
                f_name=Name(("functionA", i_6)); f_tparams=None;
                f_params=(i_7,
                          [Left3(
                             {p_variadic=None; p_attrs=None; p_modifier=None;
                              p_soft_type=None;
                              p_type=Some(Hint(
                                            XName([QI(Name(("string", i_8)))]),
                                            None));
                              p_ref=None; p_name=DName(("arg1", i_9));
                              p_default=None; })],
                          i_10);
                f_return_type=None;
                f_body=(i_11,
                        [ExprStmt(
                           Assign(
                             IdVar(DName(("localVar", i_12)), Ref(NoScope)),
                             i_13, Sc(C(Int(("1", i_14))))), i_15);
                         ExprStmt(
                           Print(i_16,
                             IdVar(DName(("undefinedVar", i_17)),
                               Ref(NoScope))), i_18);
                         ExprStmt(
                           Print(i_19,
                             IdVar(DName(("arg1", i_20)), Ref(NoScope))),
                           i_21)],
                        i_22);
                });
                ...

Dando un'occhiata all'output ho pensato che sarebbe abbastanza semplice creare un parser che potesse darmi tutti i nomi di classe o tutti i metodi o tutte le funzioni ecc.

Ho scritto un parser molto brutto che esegue un'iterazione sull'output come stringa, cerca le parole chiave, come ClassDef , quindi cerca di far corrispondere la parentesi graffa successiva e così via. Sono riuscito a estrarre alcune cose e funziona bene, ma il codice è diventato complicato e brutto molto veloce, al punto in cui non voglio più lavorare con esso e riconsiderare tale approccio. Aggiungere più funzionalità per estrarre più dati dall'AST è quasi impossibile.

Quindi ho fatto qualche ricerca in più e ho trovato fondamentalmente due approcci:

  • Roll il mio parser di discesa ricorsivo, definisci una grammatica formale per esso. Ho letto la pagina wiki per questo, ma ho avuto un momento molto difficile per andare avanti perché non ho molta esperienza con la creazione di parser. Ho letto alcuni tutorial in più, ma non sono ancora sicuro di come iniziare a analizzare una stringa complessa come quella sopra.
  • Utilizzare un tipo di framework di parser come ANTLR. A parte il fatto che non vorrei usare Java nel mio progetto, non sono nemmeno sicuro se questo sia l'approccio più semplice.

La mia soluzione ideale sarebbe avere una struttura in memoria che mi permetta di interrogare la stringa analizzata come "dammi tutti i metodi con le classi" o così o convertire l'output da sopra in XML.

Attualmente sono abbastanza bloccato su come affrontare l'analisi della struttura di cui sopra. Sarebbe molto apprezzato se qualcuno con più esperienza nella creazione di parser potesse darmi un suggerimento nella giusta direzione, forse lo sto rendendo anche troppo complicato, ma definire una grammatica e quindi magari scrivere il parser per questa struttura sembra come una grande impresa per me e non so davvero da dove cominciare.

    
posta Max 24.06.2017 - 01:24
fonte

0 risposte

Leggi altre domande sui tag