Progettino
L'obiettivo del progettino è implementare una piccola
libreria per manipolare le espressioni regolari.
Il progettino è individuale e dovrà essere consegnato
prima di sostenere la prova scritta.
Le espressioni regolari sono un modo comodo per denotare un
insieme di stringhe possibilmente infinito.
In Java, un'espressione regolare sarà rappresentata da una class
astratta RegExpr. Le sotto-class
di questa class sono:
- Empty: new Empty() denota l'insieme vuoto.
- One: new One() denota l'insieme che contiene
la sola stringa vuota "".
- Char: ha un campo che contiene un carattere e new Char('a') denota l'insieme che contiene la sola stringa "a" .
- Concat: ha due campi che contengono entrambi un'espressione regolare e new Concat(e1,e2) denota l'insieme delle stringhe che sono formate concatenando una stringa dell'insieme corrispondente a e1
con una stringa dell'insieme corrispondente a e2.
- Choice: ha due campi che contengono entrambi un'espressione regolare e new Choice(e1,e2) denota l'unione dell'insieme corrispondente a e1
e dell'insieme corrispondente a e2.
- Times: ha un campo che contiene un'espressione regolare e new Times(e)
denota l'insieme delle stringhe che sono formate concatenando
un numero arbitrario di stringhe dell'insieme corrispondente a e.
Il numero può anche essere zero, ciò sugnifica che tale insieme contiene
sempre la stringa vuota.
Per esempio,
RegExpr e = new Choice(new Times(new Concat(new Char('a'), new Char('b'))),
new Concat(new Char('a'), new Char('c')));
crea un'espressione regolare e che denota l'insieme infinito composto di "", "ab", "ac", "abab", "ababab", ...
Aggiungere nella class RegExpr:
-
un metodo pubblico toString che dà una rappresentazione sotto
forma di stringa di un'espressione regolare. Le convenzioni sono:
-
new Empty() si rappresenta come 0,
-
new One() come 1,
-
new Char('a') come a,
-
new Concat(e1,e2) come e1 . e2,
-
new Choice(e1,e2) come e1 + e2,
-
new Times(e) come (e)*.
Per esempio, e.toString() restituisce "(ab)* + ac".
-
un metodo pubblico isEmpty che indica se l'insieme denotato
dall'espressione regolare è vuoto.
Per esempio, e.isEmpty() restituisce false.
-
un metodo pubblico accept che indica se l'insieme denotato
dall'espressione regolare contiene la stringa vuota.
Per esempio, e.accept() restituisce true.
-
un overloading pubblico del metodo accept che prende un carattere c
e indica se l'insieme denotato dall'espressione regolare contiene una
stringa che inizia con il carattere c.
Per esempio, e.accept('a') restituisce true, invece
e.accept('b') restituisce false.
-
un metodo pubblico restrict che prende un carattere c
e restituisce un'expressione regolare e1 tale che una stringa
s appartiene all'insieme denotato da e1 se e solamente se
la stringa c.s appartiene all'insieme denotato dall'espressione
regolare sul quale è stato chiamato il metodo restrict.
Per esempio, e.restrict('a')
restituisce un'espressione che denota l'insieme
"b", "c", "bab", "babab", ...
per esempio b . (ab)* + c.
-
un overloading pubblico del metodo accept che prende una stringa s
e indica se s appartiene all'insieme denotato dall'espressione regolare.
Per esempio, e.accept("ab") restituisce true, invece
e.accept("aa") restituisce false. Tale metodo
dovrà appoggiarsi sui metodi accept e restrict
utilizzando il metodo toCharArray della class String
per trasformare una stringa in un array di caratteri.
Adesso, ci interessiamo ai generatori di stringhe definiti dall'interface:
interface StringGenerator {
String next();
boolean hasMoreElement();
}
Il metodo next permette di ottenere una stringa.
Il metodo hasMoreElement permette di sapere se
il generatore è vuoto. In tal caso, il metodo next
restituisce l'oggetto null.
Definire le class seguenti che implementano l'interface StringGenerator:
- ArrayStringGenerator permette di trasformare un array
di stringhe in un generatore. Per esempio,
StringGenerator sg = new ArrayStringGenerator(new String[]{"a", "b", "c"});
crea un oggetto sg tale che la prima chiamata sg.next()
restituisce la stringa "a", la seconda chiamata sg.next()
restituisce la stringa "b" e la terza chiamata sg.next()
restituisce la stringa "c". Successivamente, la chiamata sg.hasMoreElement() restituisce sempre false.
- FilteredStringGenerator permette di effettuare un filtro
su un generatore di stringhe usando un'espressione regolare rimuovendo
le stringhe nell'insieme denotato dall'espressione regolare.
StringGenerator sg1 = new ArrayStringGenerator(new String[]{"ab", "bc", "ac", "da"});
RegExpr e = new Choice(new Times(new Concat(new Char('a'), new Char('b'))),
new Concat(new Char('a'), new Char('c')));
StringGenerator sg2 = new FilteredStringGenerator(sg1, e);
crea un oggetto sg2 tale che la prima chiamata sg2.next()
restituisce la stringa "ab", la seconda chiamata sg2.next()
restituisce la stringa "ac".
Successivamente, la chiamata sg2.hasMoreElement() restituisce sempre false.
- (facoltativo) RegExprStringGenerator permette di trasformare un'espressione regolare in un generatore di stringhe.
Tutte le stringhe dell'insieme denotato dall'espressione sono generate soltanto
una volta.
RegExpr e = new Choice(new Times(new Concat(new Char('a'), new Char('b'))),
new Concat(new Char('a'), new Char('c')));
StringGenerator sg = new RegExprStringGenerator(e);
Usando sg.next() si potrà ottenere tutte le stringhe
"ab", "ac", "abab", "ababab", ...
in un ordine qualsiasi.
Il progetto dovrà essere corredato di un insieme di esempi che ne illustra
il corretto funzionamento.
Lo studente dovrebbe seguire le convenzioni di codifica
date durante il corso. Per verificare la conformità del progetto, si può
usare l'archivio checkstyle.jar.
Eseguendo
java -jar checkstyle.jar File.java
si genera un file report che indica la conformità del codice.
Laurent Théry
Last modified: Thu Feb 19 12:54:05 MET 2004