Laboratorio di Linguaggi di Programmazione 2007/2008

Transcript

Laboratorio di Linguaggi di Programmazione 2007/2008
Laboratorio di Linguaggi di
Programmazione 2007/2008
Marco Antoniotti
Giuseppe Vizzari
Automi a Stati Finiti in Common Lisp
•
Consideriamo il seguente semplice automa a stati finiti
•
Siamo in grado di scrivere un insieme di funzioni Common Lisp
che riconoscano una sequenza (P E A I P E A I P E A I P E A I)
con P stato iniziale e I stato finale
– Attenzione allo stato finale
A.A. 2007/2008
Linguaggi di Programmazione
1
Automi a Stati Finiti in Common Lisp
•
Provate a scrivere le funzioni seguenti
Stagioni : input-list → {T, NIL}
Primavera : input-list → {T, NIL}
Estate : input-list → {T, NIL}
Autunno : input-list → {T, NIL}
Inverno : input-list → {T, NIL}
•
•
Ogni funzione deve segnalare un errore quando il primo elemento
della lista di input non corrisponde allo stato
Complessivamente vogliamo ottenere un comportamento di questo
tipo:
CL> (stagioni ‘(p e a i))
T
CL> (stagioni ‘(p e a i p e a i))
T
CL> (stagioni ‘(p e a i p e a))
NIL
A.A. 2007/2008
Linguaggi di Programmazione
2
Stagioni - esempio svolto
;;; Funzione principale
(defun stagioni (seasons-list &optional (firsts T))
(cond ((null seasons-list) (if firsts nil T))
((atom seasons-list) (error "Parametro scorretto."))
(T (if (and (primavera seasons-list)
(estate (cdr seasons-list))
(autunno (cdr (cdr seasons-list)))
(inverno (cdr (cdr (cdr seasons-list))))
(stagioni (cdr (cdr (cdr (cdr seasons-list)))) nil)) ; Eventuale
T
; anno sucessivo
nil))))
;;; Funzioni di controllo stagione singola
(defun primavera (seasons-list)
(cond ((null seasons-list) nil)
(T (if (eq (car seasons-list) 'p) T
(defun autunno (seasons-list)
(cond ((null seasons-list) nil)
(T (if (eq (car seasons-list) 'a) T
(defun inverno (seasons-list)
(cond ((null seasons-list) nil)
(T (if (eq (car seasons-list) 'i) T
(defun estate (seasons-list)
(cond ((null seasons-list) nil)
(T (if (eq (car seasons-list) 'e) T
A.A. 2007/2008
nil))))
nil))))
nil))))
nil))))
Linguaggi di Programmazione
3
Ancora automi
•
Scrivere una funzione che riconosca espressioni di tipo ab*c
c
a
S0
S1
S2
b
(significa che l’espressione deve iniziare con uno e un solo
carattere a, poi un numero arbitrario di caratteri b, poi uno e un
solo c)
A.A. 2007/2008
Linguaggi di Programmazione
4
Esercizio svolto
(defun recognize-ab*c (symb-str &optional (state "s0"))
(cond ((null symb-str) (if (equal state "s2") T nil)) ;; Se sono nello stato
;; finale null è OK !!!
((atom symb-str) (error "Parametro scorretto."))
;; Stato s0 --> accetto solo il carattere a che porta a s1
;; Notare uso equal e non eq…
((equal state "s0")(if (eq (car symb-str) 'a)
(recognize-ab*c (cdr symb-str) "s1")
nil))
;; Stato s1 --> accetto il carattere b, che non fa cambiare stato
;; o il carattere c che porta a s2
((equal state "s1")(cond
((eq (car symb-str) 'b) (recognize-ab*c (cdr symb-str) "s1"))
((eq (car symb-str) 'c) (recognize-ab*c (cdr symb-str) "s2"))
(T nil))
)
;; Stato finale (ridondante, pensarci bene…)
((equal state "s2") (if (null symb-str) T nil))
)
)
A.A. 2007/2008
Linguaggi di Programmazione
5
Funzioni di ordine superiore
•
Creare una funzione che riceva due parametri a e b e crei una
funzione capace di controllare se l’unico parametro ricevuto sia
compreso all’interno dell’intervallo [a,b)
create-check-interval: number x number → fun
con
fun: number x {T,NIL}
• (defun create-check-interval (&key a b)
(lambda (num)
(if (and (>= num a) (< num b)) T nil)))
A.A. 2007/2008
Linguaggi di Programmazione
6
Funzioni di ordine superiore
•
•
Usando la funzione precedentemente definita creare una funzione conv che
accetti una lista di digit ed un parametro opzionale che indica la base nella
quale sono espressi i digit ed effettua la conversione in decimale
Es.:
CL> (conv ‘(1 3 2
4231
CL> (conv ‘(1 3 a
“Digit scorretto”
CL> (stagioni ‘(1
9
4))
4))
(più vari messaggi di errore)
0 0 1) 2)
(defun conv (digits &optional (base 10) (acc 1))
(cond ((null digits) 0)
((atom digits) nil)
;; Uso al volo la funzione di controllo dei digit ammissibili
(T (if (funcall (create-check-interval :a 0 :b base) (car digits))
;; sommo il digit corrente moltiplicato per l’accumulatore
;; con il risultato dell’invocazione ricorsiva
;; si noti che l’accumulatore viene moltiplicato per base (di default per 10)
(+ (* (car digits) acc) (conv (cdr digits) base (* base acc)))
(error "Digit scorretto.")))))
A.A. 2007/2008
Linguaggi di Programmazione
7
Automi a Stati Finiti in Common Lisp
•
La struttura delle funzioni che avete scritto dovrebbe indicarvi la
strada per costruire le seguenti funzioni
accept-dfa: input × state → {T, NIL}
delta: state × symbol → state
finalp: → state → {T, NIL}
•
•
Notate che le funzioni delta e finalp sono da definirsi a
secondo dell’automa che si vuole realizzare…
Si noti che nell’esercizio svolto la delta è facilmente
individuabile (il blocco che controlla lo stato e poi il simbolo
corrente, e poi effettua la chiamata ricorsiva), e il controllo sullo
stato finale viene effettuato quando non si hanno più simboli
A.A. 2007/2008
Linguaggi di Programmazione
8
Automi a Stati Finiti in Common Lisp
•
Usate le caratteristiche funzionali del Common Lisp e ridefinite
la funzione principale come
accept-dfa:
•
input
× state
× delta
× finalp
→ {T, NIL}
Che funzioni di default adottereste se delta e finalp
fossero opzionali?
A.A. 2007/2008
Linguaggi di Programmazione
9