#lang scheme

(require "Gramatica-Lpo.rkt")

;;Pattern-matching con variables en cualquier expresión
(define pattern-matching
  (lambda (interrogacion datum)
    (letrec
        ((lista-pares-sust '())
         (aux-pattern-matching
          (lambda (preg dato)
            (cond
              ((null? preg) lista-pares-sust)
              ((variable? (first dato))
               (let* ((par-sust (cons (first dato) (first preg)))
                      (sust-leg (sustitucion-legitima par-sust lista-pares-sust))
                      )
                 (case sust-leg
                   ((legitima) (aux-pattern-matching (rest preg) (rest dato)))
                   ((ilegitima) (set! lista-pares-sust 'fallo))
                   ((#t) (set! lista-pares-sust
                             (cons 
                              par-sust 
                              lista-pares-sust))
                         (aux-pattern-matching (rest preg) (rest dato)))
                   )))
              ((variable? (first preg))
               (let* ((par-sust (cons (first preg) (first dato)))
                      (sust-leg (sustitucion-legitima par-sust lista-pares-sust))
                      )
                 (case sust-leg
                   ((legitima) (aux-pattern-matching (rest preg) (rest dato)))
                   ((ilegitima) (set! lista-pares-sust 'fallo))
                   ((#t) (set! lista-pares-sust
                             (cons 
                              par-sust 
                              lista-pares-sust))
                         (aux-pattern-matching (rest preg) (rest dato)))
                   )))
              ((or (constante? (first preg)) (constante? (first dato)))
               (if (eq? (first preg) (first dato))
                   (aux-pattern-matching (rest preg) (rest dato)) 
                   (set! lista-pares-sust 'fallo)))
              ((and (predicado? (first preg))(predicado? (first dato)))
               (if (eq? (first preg) (first dato))
                   (aux-pattern-matching (rest preg) (rest dato)) 
                   (set! lista-pares-sust 'fallo)))
              (else 'fallo)
              ) ))
         (sustitucion-legitima
          (lambda (par-sustitucion lista-pares-sustituciones)
            (let* ((signo-var (car par-sustitucion))
                   (signo-dat (cdr par-sustitucion))
                   (hay-una (assoc signo-var lista-pares-sustituciones)) 
                   )
              (cond
                (hay-una
                 (if
                  (eq? signo-dat (cdr hay-una))
                  'legitima
                  'ilegitima))
                (else #t))
              ) ))
         )
      (aux-pattern-matching interrogacion datum)
      lista-pares-sust) ))

(provide pattern-matching)