;;; -*- Mode:Lisp; Package:DYPAR; Base:10; -*- ;;; LastEditDate = 11:07:02 Fri, 19-May-89 -- Mark Boggs ;;;--------------------------------------------------------------------- ;;; ;;; Copyright (c) 1982 ;;; by Mark Boggs ;;; all rights reserved ;;; ;;;--------------------------------------------------------------------- ;;; EXTEND.LSP ;;; HISTORY ; 18-Dic-00 Nuria Ripoll. ; Creacion de nuevo operador $nombre. ; ; 8-Nov-00 Nuria Ripoll & Moises Gil. ; Definimos la variable !!ALLPUNCT, que se supone tendria que estar ; definida en "sxreadl.lsp" pero este fichero no existe. ; ; 22-Apr-89 Mark Boggs (boggs) at Rank Xerox, Spain ; Added function application and variable passing to mapinto calls ; that do not have subpatterns. ; ; 16-Apr-89 Mark Boggs (boggs) at Rank Xerox, Spain ; Added macro def-op to ease the grammar writers burden ; when defining extension operators. ; Converted some of the defined extension operators to use def-op. ; ; 27-Jan-89 Mark Boggs (boggs) at Rank Xerox, Spain ; Converted from msg to format. ; Converted from property list patterns to structure based patterns. ; ; 14-Jan-89 Mark Boggs (boggs) at Rank Xerox, Spain ; Converted to GCL3.1 ; memq -> memb ; putprop -> ptprop ; #+ usage eliminated and all Franz dependent calls removed ; ; 03-May-84 Mark Boggs (wmb) at Carnegie-Mellon University ; Changed !non-term to a parameter of mapinto as opposed to a ; special variable. New name is non-term. ; ; 29-Feb-84 Mark Boggs (wmb) at Carnegie-Mellon University ; Added handling for (&i value) form and for naming of *var* ; generated variables. Revised comments. Changed behaviour of ; mapassoc so that a list is always returned. ; ; 04-Dec-81 Mark Boggs (wmb) at Carnegie-Mellon University ; Created. Function mapinto for variable coercion. ; (in-package "DYPAR"); :use '("LISP" "USER" "GCLISP")) (eval-when (compile) (if (not (boundp '*macros-loaded*)) (load "macros"))) (proclaim '(special !len !!punct !!allpunct !!non-pattern-operators !!default-assignments)) (defvar !!non-pattern-operators nil) (defvar !!punct '(%cr %lf %qmark %emark %period %comma %colon %semicolon)) ;;------------------------ nuria-moisés ------------------------- ;;; Lo definimos nosotros pq el fichero sxreadl.l no esxiste!! (defvar !!allpunct '(%dash %slash %apost %hash %lparen %rparen %star %bquote %rsbrack %lsbrack %bslash %vbar %dquote %lcbrack %rcbrack %labrack %rabrack %amper %percent %dollar %plus %equal %underbar %upcaret %atsign %tilde %cr %lf %qmark %emark %period %comma %colon %semicolon)) ;;--------------------------------------------------------------- ;;; !!allpunct is defined in sxreadl.l ;;; !len is set in xmatch6.lsp ;;; def-op defines dypar extension operators. All we do is pass most ;;; of the arguments directly to defun. The rest are used to set ;;; up cross-reference/function access for dypar. (defmacro def-op (name xref other-names &rest body) `(progn (defun ,name ,@body) (setcons ',name !!non-pattern-operators) (setf (get ',name :symbol) ',xref) (setf (get ',name :function) ',name) (dolist (nm ',other-names ',name) (setf (get nm :symbol) ',xref) (setf (get nm :function) ',name)))) ;;; MAPINTO is an extension function for the DYPAR-I pattern matcher. ;;; It serves the purpose of mapping a set of possible variable values into ;;; a single value to be returned when any of the possibilities match. ;;; When the pattern matcher is called with a pattern of the form: ;;; (:= !var (&i value pattern)) ;;; a successful match of `pattern' will result in `!var' being associated ;;; with `value'. `value' can be an atom or a list. If `value' is a list ;;; mapinto will check to see if the car of that list is `&apply' or `%f' ;;; If this is the case, a function-name is expected as the next element of ;;; value, followed by some number of variables to apply that function to. ;;; Variable correspondences. ;;; input -> remaining unparsed input passed to mapinto ;;; mapval -> value to return if match is successful ;;; pattern -> pattern to match against ;;; position -> position in input string when mapinto is called ;;; match-value -> result of call to pattern matcher with position and pattern ;;; as arguments ;;; mapinto returns a list of the form: ;;; ((n t (mapval) (other bindings))) ;;; where n is the new position in the input string, t is an atom telling ;;; the variable assignment clause of the pattern matcher that something ;;; special is going on, mapval is the value to be bound to a variable, and ;;; other bindings are any variable bindings that were caused in the call ;;; to smatch. If smatch fires more than once, there will be more than one ;;; valid match returned from mapinto. ;;; Other Dypar functions used: smatch funl mapassoc noassoc consp ;;; Called from: smatch1 ;;; Arguments: input calling-form ;;; Local Variables: pattern invoker mapval match-value position inv fun ;;; arguments v ;;; Global Variables: !len ;;; Calling form: (mapinto l_input (&i s_value-to-return l_pattern-to-match)) ;;; Returns: ( [(n_pos t ([a_mapval]) [l_other-bindings] )] ) (defun mapinto (input calling-form cb internal optflg non-term recurse-depth) (dlet (((invoker mapval . pattern) calling-form) ; pattern gets what's left (position (list (- !len (length input)))) (match-value)) (declare (ignore invoker)) (cond ;; if the pattern doesn't exist return the value. A list for ;; mapval is meaningless here. *** possible extension point *** ((null pattern) (if (and (consp mapval) (member (car mapval) '(%f &apply &funcall))) (let ((arguments (if (consp (car (cddr mapval))) (car (cddr mapval)) (cddr mapval)))) (list2 (car position) t (manyfy (apply (cadr mapval) (if (member (car mapval) '(&funcall %f)) (mapassoc2 arguments (cdr cb)) (mapassoc arguments (cdr cb))))))) (list2 (car position) t (list mapval)))) ;; otherwise see if the pattern matches the input. ((setq match-value (smatch (list position) pattern internal optflg non-term (1+ recurse-depth))) ;; remember that smatch returns a list of its results, and ;; that more than one valid match is possible. So we must map ;; our result across the set of match values returned. (mapcar (funl (m) (cond ;; the simplest case is (&i value pattern) ((atom mapval) (cond ;; this is for naming *var* generated vars ((memb mapval '(*var* !newvars)) (nconc (list (car m) t (mapassoc '(*var*) (cdr m))) (noassoc '(*var*) (cdr m)))) ;; the normal case (no *var* stuff) (t (nconc (list (car m) t (list mapval)) (cdr m))))) ;; the mapvalue was a list with the function ;; invocation symbol as its car. %f is here for ;; backward compatibility. ((memb (car mapval) '(%f &apply &funcall)) ;; break apart the mapval into its components (dlet (((inv fun . arguments) mapval)) ;; the grammar writer can explicitly list ;; the argument variables or not. We need ;; only one level of listing. (and (consp (car arguments)) (setq arguments (car arguments))) ;; build a value to return including the ;; results of the function call. (nconc (list (car m) t ;; if the function returns a ;; value it must be passed ;; in the form of a list. (let ((v (apply fun (or (and (memb inv '(&funcall %f)) (mapassoc2 arguments (cdr m))) (mapassoc arguments (cdr m)))))) (cond ((atom v) (list v)) (t v)))) (noassoc arguments (cdr m))))) ;; mapvalue was a list but not a function call. (t (nconc (list (car m) t mapval) (cdr m))))) match-value))))) ;;; MAPASSOC does an assoc for each element in `el-list' which must be a list ;;; and returns a list of the results. It recognizes the occurance of the ;;; DYPAR symbols `*var*' and `!newvars' and treats them specially. ;;; Each Variable value will be returned as a list. (defun mapassoc (el-list assoc-pairs) (mapcar (funl (e) (cond ((memb e '(*var* !newvars)) (mapassoc (newvars assoc-pairs) assoc-pairs)) (t (cdr (assoc e assoc-pairs))))) el-list)) (defun mapassoc2 (el-list assoc-pairs) (mapcar (funl (e) (cond ((memb e '(*var* !newvars)) (mapassoc (newvars assoc-pairs) assoc-pairs)) (t (let ((tmp (cdr (assoc e assoc-pairs)))) (or (and (cdr tmp) tmp) (car tmp)))))) el-list)) ;;; NOASSOC reaps the elements in el-list from the assoc list it is passed ;;; as an argument, returning the modified alist. It is also smart about ;;; `*var*' and `!newvars' (defun noassoc (el-list assoc-pairs) (do ((pairs assoc-pairs (cdr pairs)) (new (cond ((or (memb '*var* el-list) (memb '!newvars el-list)) (newvars assoc-pairs)) (t nil))) (ans)) ((null pairs) ans) (cond ((not (member (caar pairs) (append new el-list))) (setq ans (nconc (list (car pairs)) ans)))))) ;;; RQUOT does floating point division on integers. (defun rquot (x y) (list (quotient (float x) (float y)))) ;;; The next set of routines are the basic set of extension ;;; functions used by DYPAR and referenced in the manual. ;;; They also serve as a model for any user defined niladic ;;; extension functions. ;;; $w is used in patterns to match non-numeric non-punctuation ;;; inputs. !!allpunct is a list of all the punctuation chars. (def-op $w $ ($word) (inp) (and (litatom (car inp)) (not (memb (car inp) !!allpunct)))) ;(defun $w (l) ; (and (litatom (car l)) ; (not (memb (car l) !!allpunct)))) ;(defprop $w $ :symbol) ;(defprop $w $w :function) ;(defprop $word $w :function) ;;; $n checks for numeric inputs. (def-op $n $n ($number $numb) (inp) (numberp (car inp))) ;(defun $n (l) ; (numberp (car l))) ;(defprop $n $n :symbol) ;(defprop $n $n :function) ;(defprop $number $n :function) ;(defprop $numb $n :function) ;;; $p checks for punctuation. (def-op $p $ ($p $punc $punctuation) (inp) (member (car inp) !!allpunct)) ;(defun $p (l) ; (memb (car l) !!allpunct)) ;(defprop $p $ :symbol) ;(defprop $p $p :function) ;(defprop $punctuation $p :function) ;(defprop $punct $p :function) ;;; These next routines are to make the system a little more transparent to ;;; lisp code. (def-op $lisp-function $ () (inp) (symbol-function (car inp))) ;(defun $lisp-function (l) ; (getd (car l))) ;(defprop $lisp-function $lisp-function :function) ;(defprop $lisp-function $ :symbol) (def-op $lisp-variable $ () (inp) (boundp (car inp))) ;(defun $lisp-variable (l) ; (or (eql (car l) '%emark) ; (boundp (car l)))) ;(defprop $lisp-variable $lisp-variable :function) ;(defprop $lisp-variable $ :symbol) ;;; For Dictionary lookups. (def-op $dictionary $ ($d $dict) (inp) (get-terminal-hash (car inp))) ;(defun $dictionary (l) ; (ck-word (car l))) ;(defprop $dictionary $dictionary :function) ;(defprop $dictionary $ :symbol) ;(defprop $d $dictionary :function) ;;; &range is an example of an operator which takes arguments. ;;; We need to make sure that the grammar loading and x-ref rountines ;;; do not alter or use those arguments. (def-op &range $n (&r) (input pattern cb &rest useless) (declare (ignore useless)) (if (and (numberp (car input)) (>= (car input) (if (consp (cadr pattern)) (caratom (apply (cadr (cadr pattern)) nil)) (cadr pattern))) (<= (car input) (if (consp (caddr pattern)) (caratom (apply (cadr (caddr pattern)) nil)) (caddr pattern)))) (list (cons (1+ (car cb)) (cdr cb))))) ;(defprop &range $n :symbol) ;(defprop &range &range :function) ;;; Each of the user defined functions also needs to be identified for DYPAR ;;; by having a value associated with its function property. We have defined ;;; a number of synonyms for doing thte same thing and all of the synonyms ;;; should also have synonym: properties as mentioned above. ;;; Someday this task should be easier. (defprop &i mapinto :function) ;;; 18-Dic-00 Nuria Ripoll (def-op $nombre $ () (l) (gethash (car l) *tabla-nombres*))