;;;; -*- mode:Lisp; syntax:Common-Lisp; package:user -*- ;;;; ;;;; Copyright 1992 Patrick H. Winston. All rights reserved. ;;;; Version 1.1, copied from master file on 21 Jan 93 ;;;; ;;;; This software is licensed by Patrick H. Winston (licensor) for ;;;; instructional use with the textbooks ``Artificial Intelligence,'' by ;;;; Patrick H. Winston, and ``Lisp,'' by Patrick H. Winston and Berthold ;;;; K. P. Horn. Your are free to make copies of this software and ;;;; modify it for such instructional use as long as: ;;;; 1. You keep this notice intact. ;;;; 2. You cause any modified files to carry a prominent notice stating ;;;; that you modified the files and the date of your modifications. ;;;; This software is licensed ``AS IS'' without warranty and the licensor ;;;; shall have no liability for any alleged defect or damages. ;;;; TOP-LEVEL INTERFACE (defun run-interface () (format t "~&Welcome to the tools database. ~ Please type questions or commands,~ ~%followed by the return key, ~ or press the return key twice to stop.") (print '>) (do ((input (read-sentence) (read-sentence))) ((endp input) (format t "~&Ok---goodbye.") (values)) (unless (interface input) (format t "~&Sorry---I can't understand that.~ ~&Press the return key twice if you want to stop.")) (format t "~&~%> "))) #+comment (defun read-sentence (&aux sentence) (with-input-from-string (input (string-trim ".?!" (read-line))) (do ((word (read input nil) (read input nil))) ((not word) (return (reverse sentence))) (push word sentence)))) (defun read-sentence (&aux sentence) " Remarks: Use this alternate definition if your Lisp has trouble because the carriage returns required by UNIX are handed to read-line. Note that termination then requires two carriage returns in a row. " (labels ((strange-read-line () (let ((line (string-trim ".?!" (read-line)))) (if (zerop (length line)) (string-trim ".?!" (read-line)) line)))) (with-input-from-string (input (strange-read-line)) (do ((word (read input nil) (read input nil))) ((not word) (return (reverse sentence))) (push word sentence))))) ;;;; TREE DEFINITION AND COMPILATION (defmacro compile-tree (name tree) " Purpose: Launch COMPILE-ELEMENTS. " `(defun ,name (word-list) ,(compile-elements tree))) (defun compile-elements (tree) " Purpose: Translate grammar into a program. Remarks: Contains a COND clause for every grammar element. See the grammar data file for sample use. " (cond ((endp tree) '(values t nil word-list)) ((eq '> (first tree)) `(multiple-value-bind (result ,(second tree) word-list) (,(second tree) word-list) (when result ,(compile-elements (rest (rest tree)))))) ((eq 'brnchs (first tree)) (compile-branches (rest tree))) ((eq 'rtn (first tree)) `(values t (progn ,@(rest tree)) word-list)) ((eq 'if-end-rtn (first tree)) `(when (null word-list) (values t (progn ,@(rest tree)) nil))) (t `(let ((current-word (first word-list)) (word-list (rest word-list))) (when (eq current-word ',(first tree)) ,(compile-elements (rest tree))))))) (defun compile-branches (forms) (unless (endp forms) `(multiple-value-bind (result binding words-left-over) ,(compile-elements (first forms)) (if result (values result binding words-left-over) ,(compile-branches (rest forms))))))