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