Domanda

Come progetto per animali domestici, vorrei tentare di implementare un linguaggio di base del mio progetto che può essere utilizzato come linguaggio di scripting Web. È banale eseguire un programma C ++ come CGI di Apache, quindi il vero lavoro sta nel come analizzare un file di input contenente non-code (markup HTML / CSS) e codice lato server.

Nel mio corso di compilazione per studenti universitari, abbiamo usato Flex e Bison per generare uno scanner e un parser per un linguaggio semplice. Ci è stata data una copia della grammatica e abbiamo scritto un parser che traduceva il linguaggio semplice in un semplice assembly per una macchina virtuale. Lo scanner flessibile tokenizza l'input e passa i token al parser Bison.

La differenza tra questo e quello che mi piacerebbe fare è che come PHP, questo linguaggio potrebbe avere un semplice markup HTML e il linguaggio di scripting intervallato come segue:

<p>Hello,
<? echo "World ?>
</p>

Sono errato nel ritenere che sarebbe efficace analizzare il file di input come segue:

  1. Scansione dell'input fino a quando non viene trovato un tag di inizio dello script ('
  2. Il secondo scanner tokenizza la sezione di script sul lato server del file di input (dal tag aperto: '') e passa il token al parser, che non ha bisogno di conoscere il markup nel file.
  3. Il controllo viene restituito al primo scanner che continua questo schema generale.

Fondamentalmente, il primo scanner distingue solo tra Markup (che viene restituito direttamente al browser non modificato) e il codice, che viene passato al secondo scanner, che a sua volta tokenizza il codice e passa i token al parser.

Se questo non è un solido modello di progettazione, in che modo lingue come PHP gestiscono in modo efficiente l'input di scansione e l'analisi del codice?

È stato utile?

Soluzione

Vuoi vedere le condizioni iniziali. Ad esempio:

"<?"            { BEGIN (PHP); }
<PHP>[a-zA-Z]*  { return PHP_TOKEN; }
<PHP>">?"       { BEGIN (0); }
[a-zA-Z]*       { return HTML_TOKEN; }

Si inizia nello stato 0, utilizzare la macro BEGIN per cambiare stato. Per abbinare una RE solo mentre ci si trova in uno stato particolare, aggiungere il prefisso RE al nome dello stato racchiuso tra parentesi angolari.

Nell'esempio sopra, " PHP " è stato. & Quot; PHP_TOKEN " e " HTML_TOKEN " sono _% token_s definiti dal tuo file yacc.

Altri suggerimenti

PHP non fa distinzione tra scansione e markup. Esegue semplicemente l'output al buffer in modalità Markup, quindi passa all'analisi in modalità codice. Non hai bisogno di uno scanner a due passaggi e puoi farlo con un solo lexer flessibile.

Se sei interessato a come funziona PHP stesso, scarica la fonte (prova la fonte PHP4 è molto più facile da capire). Quello che vuoi vedere è nella directory di Zend, zend_language_scanner.l .

Avendo scritto qualcosa di simile da solo, consiglierei vivamente di ripensare seguendo la rotta Flex and Bison e andare con qualcosa di moderno come ANTLR . È molto più facile, più facile da capire (le macro utilizzate in una grammatica lex diventano molto confuse e difficili da leggere) e ha un debugger integrato ( AntlrWorks ) in modo da non dover passare ore a guardare i file di debug da 3 Meg. Supporta anche molte lingue (Java, c #, C, Python, Actionscript) e ha un libro eccellente e un ottimo sito Web che dovrebbe essere in grado di metterti in funzione in pochissimo tempo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top