(defgeneric make-term (root &optional arg) (:documentation "build a term with ROOT and ARGS")) (defgeneric root (term) (:documentation "returns the root of a term")) (defgeneric args (term) (:documentation "returns the arguments of a term")) (defgeneric zeroary-p (term) (:documentation "true if TERM is zeroary")) (defgeneric display-sequence (l stream &key sep) (:documentation "print the objects of the sequence L separated by the separator\ SEP on the STREAM")) (defmethod display-sequence ((l sequence) stream &key (sep " ")) (when l (mapc (lambda (e) (format stream "~A~A" e sep)) (butlast l)) (format stream "~A" (car (last l))))) (defclass term () ((root :reader root :initarg :root) (args :reader args :initarg :args))) (defmethod make-term (root &optional (args nil)) "builds a term with ROOT and ARGS" (make-instance 'term :root root :args args)) (defmethod print-object ((term term) stream) (format stream "~A" (root term)) (let ((args (args term))) (when args (format stream "(") (display-sequence args stream :sep ",") (format stream ")")))) (defmethod zeroary-p ((term term)) (endp (args term))) (defun leaves-names (term) "Returns a list of the states contained in the term" (let ((names '())) (labels ((names-get (term) (if (zeroary-p term) (push (root term) names) (mapc #'names-get (args term))))) (names-get term)) names)) (defun leaves-names2 (term) (if (zeroary-p term) (list (root term)) (reduce #'append (mapcar #'leaves-names2 (args term))))) (defparameter *t1* (make-term '+ (mapcar #'make-term '(1 2 3)))) (defparameter *t2* (make-term '- (mapcar #'make-term'(4 3)))) (defparameter *t3* (make-term '* (list *t1* *t2*)))