Linguaggi e
modelli computazionali LS
Manni
Tiziano
0000279932
 Realizzare un’applicazione che permetta di descrivere
movimenti ed azioni del mouse (click) e della tastiera
(pressione tasti) in modo da poterli automatizzare.
 Introdurre inoltre:
 costrutti per il controllo del flusso di esecuzione(repeat,
for, if else)
 concetti di variabile, funzione e scope di visibilità.
 Vediamo quindi un esempio del linguaggio che si vuole
ottenere:
var i;
fun Run
{
for (i=0; i<10; i=i+1)
{
doubleClick 50*i+10 300;
Esempio;
clickDx 10 10;
clickSx 40 50;
}
}
fun Esempio
{
write “simulazione tasti” + i;
}
Possibilità di collocare
frammenti di codice in
opportune procedure
 VN = <PROG, BLOCK, STATEMENT, OPERATION,
ASSIGN, DICVAR, WAIT, MOUSE, KEYBOARD,
Le funzioni
FUNCTION, EXP, TERM, FACTOR, COND, iniziano per
lettera maiuscola
CONTROL, FOR, REPEAT, IF>.
 VT = <+, -, *, /, <, >, <=, >=, ==, !=, =, id, idfun, num,
string, for, repeat, if, else, doubleClick, clickDx, clickSx,
clickSxUp, clickSxDw>.
Le variabili
iniziano per
 S = <PROG>
lettera minuscola
 Definiamo le regole di produzione del parser.
1.
<PROG> ::= { fun idfun <BLOCK> | <DICVAR> ';' }
fun Run <BLOCK>
{ fun idfun <BLOCK> | <DICVAR> ';' };
Self-Embedding
2.
Funzione di
<BLOCK>
partenza. ::=
3.
<STATEMENT> ::= <OPERATION> ';' | <CONTROL> ;
4.
< OPERATION> ::= <ASSIGN> | <DICVAR> | <WAIT> |
<MOUSE> | <KEYBOARD> | <FUNCTION> ;
5.
<CONTROL>::= for <FOR> | repeat <REPEAT> | if <IF>;
'{' { <STATEMENT> } '}';
6. <FUNCTION> ::= <idfun>;
Variabili
LOOSELY
TYPED
7. <DICVAR> ::= var id [ assign <EXP> ];
8. <ASSIGN>::= id assign <EXP>;
Può cambiare il
tipo della variabile.
L’assegnamento
non è interpretato
come operatore.
10. <EXP> ::= <TERM> { + <TERM> | - <TERM>};
11. <TERM> ::= <FACTOR> { * <FACTOR> | / <FACTOR>};
12. <FACTOR> ::= number | string | id | '(' <EXP> ')';
13. <COND>::= <EXP> ( < | > | <= | >= | ==
Operazione meno prioritaria delle
altre operazioni matematiche
Possibilità di
| !=)definire
<EXP>;
espressioni anche
fra tipo diversi.
14. <MOUSE> ::= (doubleClick | clickSx | clickDx |
clickSxUp | clickSxDw) <EXP> ' ' <EXP>;
15. <KEYBOARD> ::= write <EXP>;
16. <WAIT> ::= wait <EXP>;
Stringa da
simulare
Attesa
(espressa in
secondi)
Coordinate di
azione espresse
in pixel.
16. <FOR> ::= '(' <ASSIGN> ';' <COND> ';' <ASSIGN> ')'
<BLOCK>;
Istruzione di
inizializzazione
Blocco di
istruzioni
Istruzione di
modifica
17. <REPEAT> ::= '(' <COND> ')' <BLOCK>;
Condizione
di controllo
18. <IF> ::= '(' <COND> ')' <BLOCK> [ else <BLOCK> ];
Blocco da
eseguire con
condizione vera
… nel caso
sia falsa
 La grammatica ottenuta è di tipo 2 …
 … e risulta LL(1) in quanto per qualunque simbolo non
terminale della grammatica gli starter symbol sono
disgiunti.
→ il parser sa sempre quale produzione usare.
 Per l’analisi lessicale del programma scritto dall’utente
sono stati realizzati due componenti:
 Lo scanner: scorre la stringa (che rappresenta il programma
scritto dall’utente) e lo separa in sotto-stringhe in base ad
una lista di delimitatori.
 Il lexer che riceve dallo scanner le varie sotto-stringhe, le
esamina assegnando una corrispondente categoria lessicale:
costruisce quindi una serie di oggetti “Token” passati poi
all’analizzatore sintattico.
 Essendo la grammatica LL(1), risulta possibile utilizzare
l’analisi ricorsiva discendente per analizzare le frasi
passate in input:
1) Si introducono tante funzioni quanti i simboli non
terminali della grammatica.
2) Si fa sì che ogni funzione riconosca il sotto-linguaggio
generato da ciascun simbolo non terminale.
3) Risulta quindi semplice effettuare chiamate ricorsive di
funzioni.
 L’analisi sintattica viene svolta dal componente
Parser: esso ottiene l’istanza della classe Lexer e la
utilizza per ottenere i vari Token di cui la frase da
analizzare è costituita.
 Ricevuto in ingresso il primo Token di una frase, il
parser(essendo la grammatica LL(1)) è in grado di
richiamare la funzione corrispondente che analizzerà
la correttezza dei Token successivi.
 In caso di errore il Parser provvede a lanciare una
nuova istanza della classe ParserException.
 I visitor creati sono due, ed entrambi implementano
ovviamente la comune classe astratta “Visitor”:
 ExecuteVisitor: ha il compito di interpretare il programma
scritto da utente e simulare le azioni descritte dal
programma stesso.
 TreeViewVisitor: ha il compito di disegnare graficamente
l’albero restituito dal parser.
 Il visitor ExecuteVisitor provvede inoltre a lanciare
un’opportuna eccezione “RunTimeException” nel caso in
cui trovi frasi senza senso nel programma:
 Riferimenti a variabili non esistenti
 Tipi non compatibili.
 Utilizzo di variabili non inizializzate.
 Operatori non compatibili con gli argomenti passati.
 Richiamo di funzioni non definite.
 Per individuare errori a RunTime è stata introdotta
nell’ExecuteVisitor una modalità di simulazione
(valutazione delle variabili, espressioni e funzioni).
 L’applicazione è stata suddivisa in due thread:
 Un flusso si occupa dell’interfaccia grafica,
 L’altro flusso esegue l’ExecuteVisitor.
→ l’utente ha la possibilità di interrompere l’esecuzione in
presenza ad esempio di errori (esempio: loop infiniti, ecc).
 Inoltre è stato implementato un sistema di “generazione di
codice” per aiutare la programmazione:
 Recupero della posizione corrente del mouse e di eventuali
tasti premuti,
 Recupero del codice corrispondente ad alcuni tasti speciali
della tastiera (esempio: tab, enter, ctrl, alt, ecc).
Scanner
Programma
TreeViewVisitor
ExecuteVisitor
Lexer
Parser
 Introduzione di comandi per simulare la pressione di
combinazioni di tasti della tastiera (esempio ctrl + … ,
ctrl+alt+… , ecc. ).
 Esecuzione di funzioni con passaggio di dati.
 Introduzione di comandi per interagire con l’utente
durante l’esecuzione.
Scarica

SimMouse - Tiziano Manni