Professional Documents
Culture Documents
Cos JavaCC
partendo da una specifica di una grammatica, genera le classi Java che realizzano un analizzatore sintattico top-down per tale grammatica
Installazione
Scaricare JavaCC da: https://javacc.dev.java.net/servlets/ProjectDocumentList Decomprimere in una locazione
Es: C:\Programmi\JavaCC\javacc-4.0
Installazione (cont.)
Analizzatore Lessicale
Convertire file di Input in sequenze di token
class data{ int mese; int giorno; int anno; } void main(){ data oggi = new data(); oggi.mese = 9; oggi.giorno = 1; oggi.anno = 2007; } Sequenza di caratteri di input (es: programma sorgente Java)
class Identifier (data) left-brace Identifier (int) Identifier (mese) semicolon identifier (int) identifier (giorno) semicolon identifier (int) identifier (anno) semicolon right-brace Identifier (void) ..
Il passaggio da stringhe di caratteri a sequenze di token potrebbe essere definito da un automa a stati finiti deterministico davvero molto complesso. (si pensi a quanto complesso possa essere un linguaggio di programmazione)
Tutti i caratteri e le stringhe devono essere racchiuse tra apic i (mancano per
mancanza di spazio) Tutte le espressioni che includono * o + devono essere incluse tra parentesi
["a","b","c","d"] = ("a"|"b"|"c"|"d") ["b"-"g"] = ["b","e","f","g"] = ("b"|"e"|"f"|"g") ["b"-"f","M"-"O"] = ["b","e","f","M","N","O"] = ("b"|"e"|"f"|"M"|"N"|"O") ()? = opzionale ()+ = ()* (~["a","b"]) = qualunque carattere eccetto a o b. pu essere usato solo con [].
Input: Un insieme di espressioni regolari (una per ogni token del linguaggio) Output: Un analizzatore lessicale in Java che legge un file di input e lo separa in token
TOKEN_NAME il nome del token che deve essere descritto RegularExpression lespressione regolare che lo descrive
TOKEN: { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
Gli elementi racchiusi tra [ e ] devono essere separati da u na virgola (,) oppure dal segno meno (-).
<IDENTIFIER:<[''a''-''z'']([''a''-''z'' ''0''-''9''])*> errata
I caratteri spazio che nelle regole non sono inclusi tra apici vengono ignorati.
Metodo getNextToken()
JavaCC Il metodo getNextToken implementa lautoma a stati finiti deterministico che riconosce i token descritti dalle espressioni regolari Quando il metodo getNextToken() viene chiamato, viene ricercata lespressione che corrisponde ai successivi caratteri nelle sequenza di input e restituito il token (oggetto) per quella regola.
public int kind; Le classi Java public int beginLine; prodotteint beginColumn; public da JavaCC
// tipo del token // posizione Classi generiche:
SimpleCharStream.java deve corrispondere /* testo che Token.java token venga creato*/ ParseException.java TokenMgrError.ja
public int kind; Le classi Java public int beginLine; prodotteint beginColumn; public da JavaCC
// tipo del token // posizione Classi generiche:
SimpleCharStream.java deve corrispondere affinch il /* testo che Token.java token venga creato*/ ParseException.java TokenMgrError.ja public interface nomeParserConstants {
int int int int EOF = 0; CLASSS = 8; DO = 9; ELSE = 10;
Esempio1
Si consideri il seguente file sempliceFile.jj
PARSER BEGIN(sempliceFile) public class sempliceFile { } PARSER END(sempliceFile) TOKEN: { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
Esempio (cont.)
Si consideri il seguente input :
else;else21;
La chiamata al metodo getNextToken()tenta di risolvere la corrispondenza tra linput e le espressioni regolari presenti ne lle regole che definiscono i token.
TOKEN: { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
Esempio (cont.)
Si consideri il seguente input :
else;else21;
La chiamata al metodo getNextToken()tenta di risolvere la corrispondenza tra linput e le espressioni regolari presenti ne lle regole che definiscono i token.
TOKEN: corrisponde!! { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
Pi di una regola
Metodo getNextToken()(cont.)
JavaCC Quando pi di una espressione regolare corrisponde allinput, JavaCC adotta la seguente strategia:
Usa lespressione regolare per la corrispondenza pi lunga con linput. In caso di stessa lunghezza: usa la regola che appare per prima nel blocco TOKEN del file .jj
Esempio
Si consideri il seguente file File2.jj
PARSER BEGIN(File2) public class File2{ } PARSER END(File2) SKIP: { <'' ''> | <'\n''> | <'\t''> } Per linput: Else ; 23 for
TOKEN: { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
Esempio
Si consideri il seguente file File2.jj
PARSER BEGIN(File2) public class File2{ } PARSER END(File2) SKIP: { <'' ''> | <'\n''> | <'\t''> } Per linput: Else ; 23 for
<ELSE> < ><SEMICOLON>. TOKEN: { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
Esempio
Si consideri il seguente file File2.jj
PARSER BEGIN(File2) public class File2{ } PARSER END(File2) SKIP: { <'' ''> | <'\n''> | <'\t''> } Per linput: Else ; 23 for
getNextToken():
<ELSE> < ><SEMICOLON>. TOKEN: { <ELSE: ''else''> | <SEMICOLON: '';''> | <FOR: ''for''> | <INTEGER LITERAL: ([''0''- ''9''])+> | <IDENTIFIER: [''a''-''z'']([''a''-''z'',''0''-''9''])*> }
trovare corrispondenze con le sole regole etichettate con il medesimo stato lessicale
in cui si trova lanalizzatore stesso.
Etichetta
Trovata la corrispondenza tra lespressione regolare e una porzione dellinput, lanalizzatore passer dallo stato STATOVECCHIO allo stato STATONUOVO.
Esempio3
Si consideri il seguente file File3.jj
PARSER BEGIN(File3) public class File3{ } PARSER END(File3) SKIP: { < > | <\n> | <\t> } SKIP: { </*> : IN COMMENTO } <IN COMMENTO>: SKIP: { </*> : DEFAULT | <~[ ]> } Regole etichettate DEFAULT
Esempio3
Si consideri il seguente file File3.jj
PARSER BEGIN(File3) public class File3{ } PARSER END(File3) SKIP: { < > | <\n> | <\t> } SKIP: { </*> : IN COMMENTO } <IN COMMENTO>: SKIP: { </*> : DEFAULT |<~[ ]> }
Esempio3
Si consideri il seguente file File3.jj
PARSER BEGIN(File3) public class File3{ } PARSER END(File3) SKIP: { < > | <\n> | <\t> }
SKIP: { </*> : IN COMMENTO } <IN COMMENTO>: SKIP: { </*> : DEFAULT |<~[ ]> }
Esempio3
Si consideri il seguente file File3.jj
PARSER BEGIN(File3) public class File3{ } PARSER END(File3) SKIP: { < > | <\n> | <\t> }
SKIP: { </*> : IN COMMENTO } Passaggio da stato lessicale IN_COMMENTO a <IN COMMENTO>: stato lessicale DEFAULT SKIP: { <*/> : DEFAULT |<~[ ]> }
Per linput:
Stato Analizzatore
getNextToken()
Regole possibili
DEFAULT
Per linput:
Stato Analizzatore
getNextToken()
Regole possibili
DEFAULT DEFAULT
ELSE
Per linput:
Stato Analizzatore
getNextToken() return
Regole possibili
DEFAULT DEFAULT
ELSE
Per linput:
Stato Analizzatore
getNextToken() return
Regole possibili
ELSE
Spazio ignorato
Per linput:
Stato Analizzatore
getNextToken() return
Regole possibili
ELSE
Spazio ignorato
Per linput:
Stato Analizzatore
getNextToken() return
Regole possibili
ELSE
Spazio ignorato
/*
Per linput:
Stato Analizzatore
getNextToken() return
Regole possibili
DEFAULT DEFAULT
ELSE
Spazio ignorato
() TOKEN: { <ELSE: else> | <SEMICOLON: ;> | <FOR: for> | <INTEGER LITERAL: ([0 -9])+> | <IDENTIFIER: [a-z]([a z, 0- 9])*> }
DEFAULT
/*
ignorati
IN_COMMENTO Caratteri
..
Esempio4 (cont.)
<IN_COMMENTO> SKIP : { < "*/" > { numcomments++; SwitchTo(DEFAULT);} } <IN_COMMENTO> SKIP : { < ~[] > } TOKEN : { <ANY: ~[]>
Classi generiche: SimpleCharStream.java Token.java ParseException.java TokenMgrError.java Classi specifiche: nomeParser.java nomeParserTokenManager.java nomeParserConstants.java
token t; nomeParser tm; java.io.InputStream infile; infile = new Java.io.FileInputStream("fileName"); tm = new nomeParserTokenMenager(new SimpleCharStream(infile)); t=tm.getNextToken(); while(t.Kind != nomeParserConstants.EOF){ /*processa t */ t = tm.getNextToken(); }
Esempio
Si vuole usare un analizzatore lessicale generato da JavaCC per contare ed eliminare commenti da un file in input.
Esempio4 (cont.)
un programma java che usa lanalizzatore lessicale generato per contare ed eliminare i commenti da un file di input
class rimuoviCommenti{ public static void main(string args[]){ token t; java.io.inputStream infile; rimuoviCommentiTokenMenager tm; if (args.length < 1){ System.out.print("Inserisci un nome di file"); return;} try { infile = new java.io.FileInputStream(args[0]); }catch (Java.io.FileNotFoundException e) { System.out.println("File" + args[] + "non trovato"); return; } tm = new rimuoviCommentiTokenMenager(new SimpleCharStream(in file)); t = tm.getNextToken(); while (t.kind != rimCommentiConstants.EOF){ System.out.print(t); t=tm.getNextToken();} System.out.println("/* Numero di commenti rimossi = " + Integer.toString(tm.numCommenti) + " */"); }