(in-package "DMAP")
;;------------------------------------------------------------------------------
;;
;; File: MICRO-DMAP.LISP
;; Created: 10/19/94
;; Author: Will Fitzgerald
;;
;; Description: Direct Memory Access Parsing.
;; based on various versions of DMAP by Chris Riesbeck.
;;
;;------------------------------------------------------------------------------
;;------------------------------------------------------------------------------
;; Packages
;;------------------------------------------------------------------------------
(eval-when (load eval compile)
(unless (find-package :dmap)
(make-package :dmap)))
(in-package :dmap)
(use-package :tables)
(use-package :frames)
(export '(add-phrasal-pattern def-phrase def-phrases
parse reset-parser
clear-predictions
call-backs))
;;------------------------------------------------------------------------------
;; Data structure for predictions. These are stored in tables keyed on the
;; "target" of their first phrasal pattern element
;;------------------------------------------------------------------------------
(defclass prediction ()
((base :initarg :base :initform nil :accessor base)
(phrasal-pattern :initarg :phrasal-pattern :initform nil :accessor phrasal-pattern)
(start :initarg :start :initform nil :accessor start)
(next :initarg :next :initform nil :accessor next)
(slots :initarg :slots :initform nil :accessor slots)))
(defun make-prediction (&key base phrasal-pattern start next slots)
(make-instance 'prediction
:base base :phrasal-pattern phrasal-pattern :start start :next next :slots slots))
(eval-when (:compile-toplevel :load-toplevel :execute)
(tables:deftable anytime-predictions-on)
(tables:deftable dynamic-predictions-on))
(defun add-phrasal-pattern (base phrasal-pattern)
"Adds the phrasal pattern of base to the table of static predictions."
(if (and (eql base (first phrasal-pattern)) (null (rest phrasal-pattern)))
nil
(progn (index-anytime-prediction
(make-prediction :base base :phrasal-pattern phrasal-pattern))
phrasal-pattern)))
(defmacro def-phrase (base &rest phrasal-pattern)
(if (and (eql base (car phrasal-pattern)) (null (cdr phrasal-pattern)))
(error "~S can't reference itself" base)
`(progn (add-phrasal-pattern ',base ',phrasal-pattern)
',phrasal-pattern)))
(defmacro def-phrases (base &rest phrasal-patterns)
`(loop for phrasal-pattern in ',phrasal-patterns doing
(add-phrasal-pattern ',base phrasal-pattern)))
(defun index-anytime-prediction (prediction)
"Put the phrasal pattern/prediction in the table for its target."
(push prediction (anytime-predictions-on (prediction-target prediction))))
(defun index-dynamic-prediction (prediction)
"Put the phrasal pattern/prediction in the table for its target."
(push prediction (dynamic-predictions-on (prediction-target prediction))))
(defun predictions-on (index)
(append (anytime-predictions-on index)
(dynamic-predictions-on index)))
(defun clear-predictions (&optional (which :dynamic))
(ecase which
(:dynamic (clear-table (dynamic-predictions-on)))
(:anytime (clear-table (anytime-predictions-on)))
(:all (clear-table (dynamic-predictions-on))
(clear-table (anytime-predictions-on)))))
;;------------------------------------------------------------------------------
;; Misc. data structures.
;;------------------------------------------------------------------------------
(defvar *dmap-pos* 0) ;;global text position
;; Call backs are ad-hoc functions run when a concept (or one of its
;; specializations) is referenced. Function should take three
;; parameters: the item referenced, the start position in the text, and
;; the end position in the text.
(eval-when (:compile-toplevel :load-toplevel :execute)
(tables:deftable call-backs))
;;------------------------------------------------------------------------------
;; To parse is to reference every word in the text, looking for predictions
;; on the words.
;;------------------------------------------------------------------------------
(defun parse (sent)
(dolist (w sent)
(setq *dmap-pos* (1+ *dmap-pos*))
(reference w *dmap-pos* *dmap-pos*)))
(defun reference (item start end)
(dolist (abst (all-abstractions item))
(dolist (prediction (predictions-on abst))
(advance-prediction prediction item start end))
(dolist (fn (call-backs abst))
(funcall fn item start end))))
(defun advance-prediction (prediction item start end)
"Advancing a phrasal pattern/prediction means:
if the predicted phrasal pattern has been completely seen, to reference
the base of the prediction with the slots that have been collected;
otherwise, to create a new prediction for the next item in the
prediction phrasal pattern."
(when (or (null (next prediction))
(= (next prediction) start))
(let ((base (base prediction))
(phrasal-pattern (cdr (phrasal-pattern prediction)))
(start (or (start prediction) start))
(slots (extend-slots prediction item)))
(if (null phrasal-pattern)
(reference (find-frame base slots) start end)
(index-dynamic-prediction
(make-prediction :base base :phrasal-pattern phrasal-pattern :start start :next (1+ *dmap-pos*)
:slots slots))))))
(defun extend-slots (prediction item)
(let ((spec (first (phrasal-pattern prediction)))
(slots (slots prediction)))
(if (role-specifier-p spec)
(if (abstp item (prediction-target prediction))
slots
(cons (list (role-specifier spec) (->name item)) slots))
slots)))
(defun prediction-target (prediction)
"The target of a phrasal pattern is based on the first item in the
phrasal pattern yet to be seen.
If that item is a role-specifier, then the target is the
inherited filler of its role;
Otherwise, it is just the item itself."
(let ((spec (first (phrasal-pattern prediction))))
(if (role-specifier-p spec)
(let ((base (base prediction)))
(or (inherited-attribute-value (frame-of base) (role-specifier spec))
(error "~S not a role in ~S" (first spec) base)))
spec)))
(defun role-specifier-p (item) (keywordp item))
(defun role-specifier (item) item)
;;------------------------------------------------------------------------------
;; Resetting the parser.
;;------------------------------------------------------------------------------
(defun reset-parser ()
(setf *dmap-pos* 0)
(clear-predictions :dynamic)
t)