-
Notifications
You must be signed in to change notification settings - Fork 0
/
micro-dmap.lisp
171 lines (140 loc) · 6.71 KB
/
micro-dmap.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
(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)