Concordancia de patrones en Lisp

Anuncio
simple pattern matching
1/2
simple pattern matching
; Solo patrones sin variables: (patmat1 '(a b)'(a b))=>T
(defun patmat1 (patron lista)
(cond
((and (null patron)(null lista)) t)
((and (eql (first patron)(first lista)))
(patmat1 (rest patron)(rest lista))))
(t nil)))
; Admita utilizar comodines: (patmat2 '(a ? b ?)'(a c b a))=>T
(defun patmat2 (patron lista)
(cond
((and (null patron)(null lista)) t)
((is-? (first patron))
(patmat2 (rest patron)(rest lista)))
((and (eql (first patron)(first lista)))
(patmat2 (rest patron) (rest lista))))
(t nil)))
(defun is-? (v) (eql v '?))
2/2
; Admite además comodines de segmento
(defun patmat3 (patron lista)
(cond
((and (null patron)(null lista)) t)
((is-? (first patron))
(if (not (null lista))
(patmat3 (rest patron)(rest lista))))
((is-* (first patron))
(or (patmat3 (rest patron) nil) ; toda la lista
; o de cualquier otro tamanyo
(some #'(lambda (segmento)
(patmat3 (rest patron) segmento))
(maplist #'(lambda (x) x) lista))))
((and (eql (first patron)(first lista)))
(patmat3 (rest patron) (rest lista))))
(t nil)))
; Para comprobar el tipo comodin
(defun is-? (v) (eql v '?))
(defun is-* (v) (eql v '*))
1
pattern matching
(defun is-p (x)
;(consp nil)=>NIL
(and (consp x)
(not
(member (first x) '(? *)))))
1/4
(defun is-? (x)
(and (consp x)
(eql (first x) '?)))
(defun is-* (x)
(and (consp x)
(eql (first x) '*)))
(defun 1st-var-pat (pat)
(second (first pat)))
(defun get-pred (p)
(first (first p)))
pattern matching
2/4
(defun patmat4 (patron lista sustitucion)
(cond
((and (null patron)(null lista)) (add-lig :y :y sustitucion))
((is-? (first patron)) (match-? patron lista sustitucion))
((is-* (first patron)) (match-* patron lista sustitucion))
((is-p (first patron)) (match-p patron lista sustitucion))
(t (and (eql (first patron)(first lista))
(patmat4 (rest patron) (rest lista) sustitucion)))))
(defun match-? (patron lista sustitucion)
(let* ((var (1st-var-pat patron))
(ligadura (get-lig var sustitucion)))
(if ligadura
; si hay ligadura debe ser eql con first de lista y sigo
(and (eql (first lista) (val-lig ligadura))
(patmat4 (rest patron)(rest lista) sustitucion))
; si no hay ligadura, anyado una nueva y sigo adelante
(patmat4 (rest patron)(rest lista)
(add-lig var (first lista) sustitucion)) )))
(defun add-lig (var val subst) (defun val-lig (lig)
(acons var val subst))
(cdr lig))
(defun get-lig (var subst)
(assoc var subst))
2
(defun val (var subst)
(cdr (assoc var subst)))
(defun match (patron lista)
(patmat4 patron lista nil))
3
4
pattern matching
3/4
pattern matching
(defun match-* (patron lista sustitucion)
(let* ((var (1st-var-pat patron))
(ligadura (assoc var sustitucion)))
(if ligadura
; si hay lig. compruebo que el sufijo de la lista concuerde
(let* ((sgto (val-lig ligadura))
(long (length sgto))
(lista-sgto (nthcdr long lista)))
(and (equal (append sgto lista-sgto) lista)
(patmat4 (rest patron) lista-sgto sustitucion)))
; si no la hay
(or
; o la variable de segmento es nula
(patmat4 (rest patron) lista
(add-lig var nil sustitucion))
; o concuerda con uno o mas elementos de lista
(match-sto var patron lista sustitucion)))))
4/4
(defun match-sto (var patron lista sustitucion)
(do* ((lst lista (rest lst))
sufijo prefijoInv result)
((or result (null lst)) result)
(push (first lst) prefijoInv)
(setq sufijo (rest lst))
(setq result
(patmat4 (rest patron) sufijo
(add-lig var (reverse prefijoInv) sustitucion)))))
(defun match-p (patron lista sustitucion)
(if (apply (get-pred patron) (list (first lista)))
(patmat4 (rest patron) (rest lista)
(add-lig (1st-var-pat patron)
(first lista)
sustitucion))))
5
6
Descargar