;;; -*- Mode:Lisp; Package:DYPAR; Base:10; -*- ;;; ---------------------------------------------------------------- ;;; ;;; (c) Copyright, 1989 ;;; by Mark Boggs and Jesus Gonzalez Boticario ;;; All rights reserved ;;; ;;; ---------------------------------------------------------------- ;;; STRUC.LSP ;;; HISTORY ; 23-Oct-89 Jesus Gonzalez Boticario para Rank Xerox, Espa¤a ; Reducci¢n del c¢digo para la versi¢n "runtime". ; 24-Apr-89 Mark Boggs (boggs) at Rank Xerox, Spain ; Added constants, required, consumes, and forced fields to the ; general rule structure. ; Added structure printing functions. ; ; 09-Apr-89 Mark Boggs (boggs) at Rank Xerox, Spain ; Added functions for removing rules and terminals. ; Added functions to delete individual elements from where and lwhere ; Added generic parent macro. ; Added selective delete macros for all fields containing lists. ; ; 15-Dec-88 Mark Boggs (boggs) at Rank Xerox, Spain ; Created. ; Contains macros for manipulating rule and terminal structures. (in-package "DYPAR") ;;; Make sure our macro package is here for compilation. (eval-when (compile) (if (not (boundp '*macros-loaded*)) (load "macros"))) ;;; For efficient look-up, as well as avoiding symbol conflicts, we store ;;; our structures in a hash table. (defvar *dypar-structure-hash* (make-hash-table :size 453 :rehash-size 1.4)) ;;; To add a new rule structure to the hash table. (defmacro put-rule-hash (key struc) `(setf (gethash ,key *dypar-structure-hash*) ,struc)) ;;; Access a rule structure (defmacro get-rule-hash (key) `(gethash ,key *dypar-structure-hash*)) (defmacro rule (key) `(gethash ,key *dypar-structure-hash*)) ;;; Delete a rule structure. (defmacro remove-rule-hash (key) `(remhash ,key *dypar-structure-hash*)) (defvar *dypar-terminal-hash* (make-hash-table :size 453 :rehash-size 1.4)) ;;; To add a new terminal structure to the hash table. (defmacro put-terminal-hash (key struc) `(setf (gethash ,key *dypar-terminal-hash*) ,struc)) ;;; Access a terminal structure. (defmacro get-terminal-hash (key) `(gethash ,key *dypar-terminal-hash*)) (defmacro term (key) `(gethash ,key *dypar-terminal-hash*)) ;;; Delete a structure. (defmacro remove-terminal (key) `(remhash ,key *dypar-terminal-hash*)) ;;; Add a terminal to the hash table while creating the associated ;;; structure. (defmacro new-terminal-hash (term &rest struc-args) `(put-terminal-hash ,term (make-terminal :name ,term ,@struc-args))) ;;; DyparI includes three types of grammar rules (top-level, transformation ;;; and non-terminal). The Xreference operation generates some information ;;; which is common to all dypar rule types. Thus we define a common ;;; structure to contain those common elements. This makes retreiving ;;; data depend on exactly the same function name for each rule type. (defstruct (dypar-xref-values (:conc-name dxv-)) (name nil :type symbol) ; the name of the rule (pattern nil :type list) ; its pattern (first nil :type list) ; those words which can iniciate ; a pattern. (last nil :type list) ; those words which can terminate ; a pattern (fwild nil :type symbol) ; a flag indicating if a wildcard ; match is possible at the start (lwild nil :type symbol) ; a flag indicating if a wildcard ; match is possible at the end (opt nil :type symbol) ; is the pattern completely optional (variables nil :type list) ; names of variables used in pattern (terminals nil :type list) ; terminals referenced in pattern ) ;;; We want to be able to update these structure fields relatively painlessly ;;; The following macros, given a structure and a value will update or access ;;; appropriate field. Those structure fields which contain lists also ;;; have a function for selective deletion of information. ;;; ACCESS & UPDATE FUNCTIONS: ;;; (set-FIELD rule value) ;;; (get-FIELD rule) ;;; (delete-SINGULAR_FIELD rule value) ;;; only in first, last, fchildren (fchild), lchildren (lchild), ;;; variables (variable), terminals (terminal) ;;; and constants (constant). (defmacro set-pattern (rname pattern) `(setf (dxv-pattern (get-rule-hash ,rname)) ,pattern)) (defmacro get-pattern (rname) `(dxv-pattern (get-rule-hash ,rname))) (defmacro set-first (struc first-list) `(setf (dxv-first (get-rule-hash ,struc)) ,first-list)) (defmacro get-first (struc) `(dxv-first (get-rule-hash ,struc))) (defmacro delete-first (struc first) `(setf (dxv-first (get-rule-hash ,struc)) (delete ,first (get-first ,struc)))) (defmacro set-last (struc last-list) `(setf (dxv-last (get-rule-hash ,struc)) ,last-list)) (defmacro get-last (struc) `(dxv-last (get-rule-hash ,struc))) (defmacro delete-last (struc last) `(setf (dxv-last (get-rule-hash ,struc)) (delete ,last (get-last ,struc)))) (defmacro set-terminals (struc terminals) `(setf (dxv-terminals (get-rule-hash ,struc)) ,terminals)) (defmacro get-terminals (struc) `(dxv-terminals (get-rule-hash ,struc))) (defmacro delete-terminal (struc terminal) `(setf (dxv-terminals (get-rule-hash ,struc)) (delete ,terminal (get-terminals ,struc)))) (defmacro set-variables (struc variables) `(setf (dxv-variables (get-rule-hash ,struc)) ,variables)) (defmacro get-variables (struc) `(dxv-variables (get-rule-hash ,struc))) (defmacro delete-variable (struc variable) `(setf (dxv-variables (get-rule-hash ,struc)) (delete ,variable (get-variables ,struc)))) (defmacro set-fwild (struc fwild) `(setf (dxv-fwild (get-rule-hash ,struc)) ,fwild)) (defmacro get-fwild (struc) `(dxv-fwild (get-rule-hash ,struc))) (defmacro set-lwild (struc lwild) `(setf (dxv-lwild (get-rule-hash ,struc)) ,lwild)) (defmacro get-lwild (struc) `(dxv-lwild (get-rule-hash ,struc))) (defmacro set-opt (struc opt) `(setf (dxv-opt (get-rule-hash ,struc)) ,opt)) (defmacro get-opt (struc) `(dxv-opt (get-rule-hash ,struc))) ;;; For each real dypar rule type we define a structure which includes the ;;; common information fields as well as rule-type specific fields. (defstruct (non-terminal (:conc-name nt-) (:constructor make-nt) (:include dypar-xref-values) (:print-function non-terminal-print-function)) (parents nil :type list) ) (defmacro set-nt-parents (struc parent) `(setf (nt-parents (get-rule-hash ,struc)) ,parent)) (defmacro add-nt-parent (term parent) `(setf (nt-parents (get-rule-hash ,term)) (dy-insert ,parent (get-nt-parents ,term)))) (defmacro get-nt-parents (struc) `(nt-parents (get-rule-hash ,struc))) (defmacro delete-nt-parent (struc parent) `(setf (nt-parents (get-rule-hash ,struc)) (delete ,parent (get-nt-parents ,struc)))) (defstruct (top-level-rule (:conc-name tl-rule-) (:constructor make-tl-rule) (:include dypar-xref-values) (:print-function top-level-rule-print-function)) (action nil :type t) (internal-strategy nil :type list) (external-strategy nil :type list) ) (defmacro set-action (rname action) `(setf (tl-rule-action (get-rule-hash ,rname)) ,action)) (defmacro get-action (rname) `(tl-rule-action (get-rule-hash ,rname))) (defmacro set-in-strat (rname strat) `(setf (tl-rule-internal-strategy (get-rule-hash ,rname)) ,strat)) (defmacro get-in-strat (rname) `(tl-rule-internal-strategy (get-rule-hash ,rname))) (defmacro set-ex-strat (rname strat) `(setf (tl-rule-external-strategy (get-rule-hash ,rname)) ,strat)) (defmacro get-ex-strat (rname) `(tl-rule-external-strategy (get-rule-hash ,rname))) (defstruct (terminal (:print-function terminal-print-function)) (name nil :type symbol) (where nil :type list) (lwhere nil :type list) (parents nil :type list) ) (defmacro set-terminal-parents (struc parent) `(setf (terminal-parents (get-terminal-hash ,struc)) ,parent)) (defmacro add-terminal-parent (term parent) `(setf (terminal-parents (get-terminal-hash ,term)) (dy-insert ,parent (get-terminal-parents ,term)))) (defmacro get-terminal-parents (struc) `(terminal-parents (get-terminal-hash ,struc))) (defmacro delete-terminal-parent (term parent) `(setf (terminal-parents (get-terminal-hash ,term)) (delete ,parent (get-terminal-parents ,term)))) (defmacro set-where (term where) `(setf (terminal-where (get-terminal-hash ,term)) ,where)) (defmacro add-where (term where) `(setf (terminal-where (get-terminal-hash ,term)) (dy-insert ,where (get-where ,term)))) (defmacro get-where (term) `(and (get-terminal-hash ,term) (terminal-where (get-terminal-hash ,term)))) (defmacro delete-where (term where) `(setf (terminal-where ,term) (delete ,where (get-where ,term)))) (defmacro set-lwhere (term where) `(setf (terminal-lwhere (get-terminal-hash ,term)) ,where)) (defmacro add-lwhere (term where) `(setf (terminal-lwhere (get-terminal-hash ,term)) (dy-insert ,where (get-lwhere ,term)))) (defmacro get-lwhere (term) `(and (get-terminal-hash ,term) (terminal-lwhere (get-terminal-hash ,term)))) (defmacro delete-lwhere (term lwhere) `(setf (terminal-lwhere ,term) (delete ,lwhere (get-lwhere ,term)))) ;;; Because there are two distinct structure types for non-terminals ;;; and terminals we provide this function to make the choice as to ;;; which of the two is being modified. (defmacro add-parent (term parent) `(if (non-terminal-p (get-rule-hash ,term)) (add-nt-parent ,term ,parent) (add-terminal-parent ,term ,parent))) (defmacro get-parents (term) `(if (non-terminal-p (get-rule-hash ,term)) (get-nt-parents ,term) (get-terminal-parent ,term))) (defun non-terminal-print-function (struc stream depth) (declare (ignore depth)) (format stream "~&Rule-name: ~S~&" (dxv-name struc)) (format stream " Pattern: ~S~&" (dxv-pattern struc)) (format stream " First Wild: ~S Last Wild: ~S Optional: ~S" (dxv-fwild struc) (dxv-lwild struc) (dxv-opt struc)) (format stream " First: ") (pprint (dxv-first struc) stream) (format stream " Last: ") (pprint (dxv-last struc) stream) (format stream " Terminals: ") (pprint (dxv-terminals struc) stream) (format stream " Variables: ~S~&" (dxv-variables struc)) (format stream " Parents: ~S~&" (nt-parents struc)) t) (defun top-level-rule-print-function (struc stream depth) (declare (ignore depth)) (format stream "~&Rule-name: ~S~&" (dxv-name struc)) (format stream " Pattern: ~S~&" (dxv-pattern struc)) (format stream " Action: ~S~&" (tl-rule-action struc)) (format stream " First Wild: ~S Last Wild: ~S Optional: ~S" (dxv-fwild struc) (dxv-lwild struc) (dxv-opt struc)) (format stream " First: ") (pprint (dxv-first struc) stream) (format stream " Last: ") (pprint (dxv-last struc) stream) (format stream " Terminals: ") (pprint (dxv-terminals struc) stream) (format stream " Variables: ~S~&" (dxv-variables struc)) (format stream " Internal Strategy: ~S~&" (tl-rule-internal-strategy struc)) (format stream " External Strategy: ~S~&" (tl-rule-external-strategy struc)) t) (defun terminal-print-function (struc stream depth) (declare (ignore depth)) (format stream "~&Terminal: ~S~&" (terminal-name struc)) (format stream " Parents: ~S~&" (terminal-parents struc)) (format stream " First Where: ~S~&" (terminal-where struc)) (format stream " Last Where: ~S~&" (terminal-lwhere struc)) t) ;;; To prove that a file has been loaded at least once we set a variable ;;; which can be used by other files to check for this fact. (defvar *struc-loaded* t)