Javascript TIP – addslashes

Dopo svariate ricerche e inutili tentativi sono riuscito a definire una funzione per l’aggiunta di slash per gli apici e doppi apici.

function addslashes(str) {
 
	return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
	}

Spero che sia utile a qualcuno ed eviti un bel po’ di mal di testa..

Linux, python e problemi di ottimizzazione

Glpk è un tool per risolvere dei problemi di programmazione lineare rilasciato sotto licenza GNU. Esso viene rilasciato un due formati: uno come eseguibile a riga di comando e un’altro come libreria dinamica. E’ stato realizzato un binding per python (ce ne sono anche per altri linguaggi) che permette di sottomettere un problema di programmazione lineare al risolutore ed avere la risposta direttamente dall’ambiente interpretato di python. Non starò qui a discutere sulla bontà (ossia, sull’efficienza) di tale risolutore rispetto alle sue controparti commerciali. Alcuni articoli e documentazioni sono reperibili nel sito ufficiale di glpk e spiegano anche gli algoritmi implementati per risolvere problemi di programmazione lineare. Ciò che invece mi piace osservare è la flessibilità di python come linguaggio di scripting. Di frequente python viene usato come linguaggio per uso scientifico/matematico, anche se è diventato famoso per la facilità di programmazione di strumenti per web. Non sono mai stato portato a realizzare applicazioni totalmente in python, ma lo uso molto spesso per avere una componente flessibile a run-time che realizzi un determinato compito. Ad esempio, usare python per risolvere istanze di problemi di programmazione lineare o combinatorici rappresenta una buona soluzione all’interno di un’applicazione più grande scritta in un linguaggio non interpretato come C/C++ oppure java o C# (Jython, IronPython). In questo modo, l’applicazione dovrà solo preoccuparsi di formattare l’input utente comprensibile a script python e lanciarli per la soluzione.

ES:

#include <Python.h>
 
int
main(int argc, char *argv[])
{
  Py_Initialize();
  PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
  Py_Finalize();
  return 0;
}

Non andando oltre confermo che è possibile lanciare interi script da programmi c o c++. Implementando algoritmi di ottimizzazione in python, possiamo separare la parte del software relativa alla presentazione dei risultati con quella relativa alla risoluzione del problema. Infatti, sarà necessario solo scrivere nuovo codice python per aggiungere un nuovo algoritmo. Una soluzione simile, ma per scopi diversi, è quella usata da blender. Blender infatti usa python per scrivere plug-in, come ad esempio importer o exporter di formati di modelli 3d.

Passiamo ora all’oggetto del topic. Premetto che il binding di glpk per python è più semplice da installare per linux, anche se non ho tentato di farlo per win. Infatti, sotto ubuntu basta impartire il seguente comando:

sudo apt-get install python-glpk

per avere tutto a disposizione. Scrivere un problema di programmazione lineare è molto semplice dando in input un file .mod:

ES:

var x >=0 integer;
var y >= 0;

maximize z: x + y;

subject to r:
x + y <= 10;
subject to s:
x + 10*y <= 1;
subject to t:
10*x + y <= 1;

end;

Salviamo il contenuto in un file chiamato example.mod. Da python lanciamo il seguente script:

import glpk
 
print "starting..."
example = glpk.lpx("example.mod")
example.solve()
print "solution:", example.sol
print "solution is also here:", example.x

Il risultato sarà il seguente:

>>>
starting…
solution: {’y': 0.099999999999999992, ‘x’: 0, ‘z’: 0.099999999999999992}
solution is also here: array(’d', [0.099999999999999992, 0.0, 0.099999999999999992])

il campo example.sol ci da la soluzione sotto forma di dizionario, mentre il campo example.x ci da la soluzione sottoforma vettoriale. Per chi ha bisogno di una libreria più avanzata consiglio PuLP contenente una documentazione accurata e molte soluzioni implementative a problemi noti.

Applicazioni Desktop con Eclipse (RCP)

Alla domanda : che cos’è eclipse ? Molti di voi risponderanno: “è un IDE”. Alcuni diranno: “Si, ma ha delle funzionalità tipiche anche di un RAD”. Entrambi hanno ragione, ma eclipse è anche molto di più. Esso infatti permette di costruire applicazione stand-alone facendo uso dell’architettura stessa di eclipse. Ossia, creare applicazione estensibili, flessibili e riusabili. Tutto questo va sotto il nome di RCP ( Rich Client Platform). Perchè usare questa tecnologia anzichè JFC/Swing o AWT è facilmente intuibile: “l’architettura”. Chi di voi ha esperienze con le applicazioni desktop (ma vale anche per l’enterprise) sa come sono difficili da mantenere e come sia difficoltoso aggiungere nuove funzionalità se non si è stati attenti a dare all’applicazione una struttura modulare che faciliti il refactoring. Usando una struttura estensibile a plug-in come quella che usa eclipse nelle nostre applicazioni è senz’altro un grande vantaggio e per di più a costo zero ( o quasi). Eclipse RPC permette di ereditare lo stesso framework usato da Eclipse Workbench quindi permette al programmatore di dividere le funzionalità applicative in diversi plug-in. Per iniziare a programmare applicazioni usando RCP è possibile scaricare una versione apposita di eclipse con tutti i plugin necessari, inoltre è disponibile un tutorial abbastanza completo per la programmazione.

Refs

Eclipse RCP/ Ganymede

Eclipse RCP Tutorial

Good programming!

JSE , Swing e JFileChooser

E’ ormai risaputo che la classe JFileChooser è tra le più problematiche in termini di performance. Al primo avvio, il dialog prende circa 7/8 secondi su un PC dotato di un’intel da 1.5 Ghz e 512 MB di memoria e la cosa sembra migliorare di poco anche con hardware migliore. Ero molto scontento di tale performance che persiste anche nella versione 1.6 della JVM. L’unico modo per poter migliorare la situazione è usare il controllo nativo di windows, richiamabile tramite la classe java.awt.FileDialog.  La grafica di tale controllo ovviamente è meno ricca e bella da vedere, ma la velocità di caricamento e visualizzazione è notevolmente migliorata ( circa del 80%). Infatti la classe FileDialog fa apparire il controllo in circa 1/2 secondi al primo avvio e diventa istantaneo nei successivi. Benchè le performance delle JFC/Swing siano notevolmente migliorate nella nuova versione rispetto alle precedenti, programmare applicazioni desktop in Java ha ancora bisogno di qualche trucco da volpe come questo. Per la Java 6 direi che la gestione degli eventi tramite Action condivise ha migliorato notevolmente le respositività del software ad eventi esterni.

TIP del giorno : Usare java.awt.FileDialog invece di javax.swing.JFileChooser per aprire o salvare file.

Breve tutorial sul parsing e analisi lessicale (Java)

In questo articolo esporrò le tecniche usate per poter creare degli analizzatori lessicali e parser in Java, usando degli strumenti gratuiti ( JFlex e byacc/J). In questo modo è facile creare un nuovo linguaggio di programmazione o più semplicemente creare un programma che estrae le parti significative da un input testuale, quale può essere un file in lettura o una stringa inserita da linea di comando, e le elabora a seconda della sintassi predefinita dal programma. Si pensi ad esempio ad un programma che prenda un’espressione numerica in input con variabili e costanti numeriche e ne calcoli il risultato stando attento a come usare le parentesi tramite una gerarchia prestabilità ( prima le parentesi tonde, poi le quadre ed in ultimo le graffe). Il problema è più complesso di quanto sembri, ad esempio si immagini un file sorgente C con la stringa:

int x;
x = 0;

E’ evidente come alla frase “int” si debba dare un significato e prima ancora occorre un modo per poter estrarre la frase “int” dal file. Questo causa molti problemi, se non trattati adeguatamente, in casi del genere:

int intero;
intero = 0;

Siccome un analizzatore lessicale legge uno stream di caratteri partendo dal primo byte, la domanda che dobbiamo porci è come fa nelle precedente seconda riga a sapere se si deve fermare ai primi tre caratteri perchè ha trovato una parola chiave oppure deve continuare a leggere per prendere l’identificatore “intero” ? Molti testi sono stati scritti riguardanti la teoria dei compilatori e su gli algoritmi che vengono usati per poter risolvere il problema precedente. In questo articolo non ci sofferemeremo su gli aspetti teorici come l’algortimo di Thompson, ma cercherò di mostrare come in poche righe di codice è possibile definire un’analizzatore lessicale abbastanza complesso e un parser che riconosce una grammatica predefinta da noi.

// File .flex in ingresso a JFlex.
 
%%
 
%byaccj
 
%{
  private Parser yyparser;
 
  public Yylex(java.io.Reader r, Parser yyparser) {
    this(r);
    this.yyparser = yyparser;
  }
 
%}
 
ID = [a-zA-Z]([a-zA-Z0-9_])*
NUM = [0-9]+
FLOATNUM = {NUM}"."{NUM}
 
%% 
 
{ID}    {      /*Salva il valore dell'ID  in yyparser.yylval
                  e lo passa in input al parser*/
                  yyparser.yylval=new ParserVal(yytext());
                  return Parser.ID;
           }
 
"+"          {return (int) yycharat(0);}
"-"          {return (int) yycharat(0);}
"/"          {return (int) yycharat(0);}
"*"          {return (int) yycharat(0);}
"("          {return (int) yycharat(0);}
")"          {return (int) yycharat(0);}
\n           {return (int) yycharat(0);}
{FLOATNUM}   {yyparser.yylval= new ParserVal(yytext());
                     return Parser.FLOATNUM;}
{NUM}        {yyparser.yylval= new ParserVal(yytext());
                  return Parser.NUM;}
[ \t\b\r]    { // Skip }
%%

Ora, salvando il codice precedente in un file con estensione .flex e aprendolo con JFlex, se tutto è andato a buon fine quest’ultimo dovrebbe fornirci un file chiamato Yylex.java pronto per essere incluso nel nostro progetto. In pratica questa classe non ci è ancora molto utile perchè stiamo usando JFlex in coppia con Byacc/J e non singolarmente. Se omettessimo la direttiva:

%byaccj

potremmo usare la classe precendente per scandagliare un file in input contente espressioni aritmetiche ed estrarre tutte le sue componenti, ad esempio :

(1+2) – 3

prenderebbe il carattere “(” poi 1 come token NUM poi “+” ecc. tralasciando eventuali spazi di tabulazione intermedi.Da notare come il codice racchiuso tra parentesi graffe viene eseguito ogni volta che viene incontrato un token o lessema valido, ossia che rispecchia un’espressione regolare. Quindi, invece di passare l’argomento al parser un programma JFlex può benissimo eseguire altre operazioni.

Per poter dare un significato a tale espressione è necessario fornire una sintassi e una semantica. La semantica ovviamente è banale per quest’esempio come pure la sintassi, ma entrambi possono essere costruite in modo agevole con un genereatore di parser come byaccj.

%{
 
%}
 
%token ID
%token NUM
%token FLOATNUM
 
%start input // produzione di inizio
 
%left '+' '-' '*' '/'  // Associatività degli operatori
 
%% 
 
input:
        |
         input '\n' {/* Salta una riga vuota per
                          far avanzare il parser */
                        }
        | input exp  { System.out.println($2.sval);}
        ;
 
exp : exp '+' exp {$$.sval = $1.sval +  $3.sval;}
    |  '(' exp ')' {$$.sval =  $2.sval;}
    | exp '-' exp  {$$.sval = $1.sval -  $3.sval;}
    | exp '*' exp   {$$.sval = $1.sval  *  $3.sval;}
    | exp '/' exp   {$$.sval = $1.sval / $3.sval;}
    | NUM {$$.sval = $1.sval;}
    | FLOATNUM {$$.sval = $1.sval;}
    | ID { /*Recupera il valore dell'identificatore e memorizzalo in $$.sval,
               non implementato*/}
    ; 
 
%% 
 
private Yylex lexer;
 
  private int yylex () {
    int yyl_return = -1;
    try {
      yylval = new ParserVal(0);
      yyl_return = lexer.yylex();
    }
    catch (IOException e) {
      System.err.println("IO error :"+e);
    }
    return yyl_return;
  }
 
  public void yyerror (String error) {
    System.err.println ("Syntatic Error: " + error);
  }
 
  public Parser(Reader r) {
 
     lexer = new Yylex(r, this);
  }
 
 public static void main(String args[]) throws IOException {
 
    Parser yyparser;
 
    String input = "(1+2)-2"; 
 
    if ( args.length &gt; 0 ) {
 
      yyparser = new Parser( new java.io.StringReader(input));
       yyparser.yyparse();
 
    }else{
 
      System.exit(0);
    }

Salviamo il codice precendente in un file con estensione .y , ad esempio Parser.y (attenzione il nome del file è significativo per la classe in output, vedere la doc di byacc/j).Pre creare il parser è necessario richiamare byaccj con i seguenti argomenti:

yacc.exe -J Parser.y

L’esempio precedente non fornisce propriamente una calcolatrice perchè è stata omessa la parte relativa alla gestione dei tipi dei token i quali sono considerati tutti di tipo String. Leggendo accuratamente la documentazione di byacc/j ed i riferimenti seguenti non è difficile superare tale limitazione.

JFlex fornisce una comoda interfaccia grafica per poter creare il nostro analizzatore lessicale senza bisogno di usare la shell o il prompt.

Riferimenti

Aho, Sethi, Ullman, Compilers: Principles, Techniques, and Tools. Per maggiori dettagli vedere qui.

byaccj

JFlex