; Count the operators in your DSL
; ------------------------------
; The Little Lisper 3rd Edition
; Chapter 7
; Exercise 3
; Common Lisp
; http://t...content-available-to-author-only...r.com/thelittlelisper
; http://t...content-available-to-author-only...t.com/2010/06/little-lisper-chapter-7-shadows.html
; http://t...content-available-to-author-only...t.com/2010/06/little-lisper.html
; ------------------------------
(setf l1 '())
(setf l2 '(3 + (66 6)))
(setf aexp1 '(1 + (3 * 4)))
(setf aexp2 '((3 ^ 4) + 5))
(setf aexp4 5)
; ------------------------------


(defun sub1 (n)
  (- n 1))

(defun operator (aexp_)
  (car (cdr aexp_)))

(print (operator '(1 + 2)))
;+

(defun isoperator (a)
  (cond
   ((null a) NIL)
   ((eq a '+) t)
   ((eq a '*) t)
   ((eq a '^) t)
   (t NIL)))


(print (isoperator '^))
;T

(defun 1st-sub-expr (aexp_)
  (car aexp_))

(print (1st-sub-expr '(1 + 2)))
;1

(defun 2nd-sub-expr (aexp_)
  (car (cdr (cdr aexp_))))

(print (2nd-sub-expr '(1 + 2)))
;2

(defun number_ (n)
  (cond
   ((null n) t)
   (t (and
       (null (car n))
       (number_ (cdr n))))))
       
(defun notatom (lat)
  (not (atom lat)))

(defun number__ (n)
  (cond
   ((null n) nil)
   ((notatom n) nil)
  ((= 0 n) t)
   (t (number__ (sub1 n)))))       


(defun mk+exp (aexp1_ aexp2_)
  (cons aexp1_
        (cons '+
              (cons aexp2_ '()))))

(defun mk*exp (aexp1_ aexp2_)
  (cons aexp1_
        (cons '*
              (cons aexp2_ '()))))

(setf aexp1 (mk+exp 1 (mk*exp 3 4)))
(setf aexp3 (mk*exp 3 (mk*exp 4 (mk*exp 5 6))))

(defun count-op (aexp_)
  (cond
   ((null aexp_) 0)
   ((number__ aexp_) 0)
   ((isoperator (operator aexp_))
    (+ 
    (+ 1 (count-op (1st-sub-expr aexp_)))
    (count-op (2nd-sub-expr aexp_)))
    )
   (t 0)))

(print (count-op '(1 + 2)))
;1

(print (count-op aexp1))
;2

(print (count-op aexp3))
;3

(print (count-op aexp4))
;0

(defun countatomplus (a)
  (cond
   ((null a) 0)
   ((eq a '+) 1)
   (t 0)))

(print (countatomplus '*))
;0

(print (countatomplus '+))
;1

(defun count+ (aexp_)
  (cond
   ((null aexp_) 0)
   ((number__ aexp_) 0)
   ((isoperator (operator aexp_))
    (+ 
    (+ (countatomplus(operator aexp_)) (count+ (1st-sub-expr aexp_)))
    (count+ (2nd-sub-expr aexp_)))
    )
   (t 0)))

(print (count+ aexp1))
;1

(defun countatomtimes (a)
  (cond
   ((null a) 0)
   ((eq a '*) 1)
   (t 0)))

(defun count* (aexp_)
  (cond
   ((null aexp_) 0)
   ((number__ aexp_) 0)
   ((isoperator (operator aexp_))
    (+ 
    (+ (countatomtimes(operator aexp_)) (count* (1st-sub-expr aexp_)))
    (count* (2nd-sub-expr aexp_)))
    )
   (t 0)))

(print (count* aexp1))
;1


(print (count* aexp3))

(defun countatomexp (a)
  (cond
   ((null a) 0)
   ((eq a '^) 1)
   (t 0)))

(defun count^ (aexp_)
  (cond
   ((null aexp_) 0)
   ((number__ aexp_) 0)
   ((isoperator (operator aexp_))
    (+ 
    (+ (countatomexp(operator aexp_)) (count^ (1st-sub-expr aexp_)))
    (count^ (2nd-sub-expr aexp_)))
    )
   (t 0)))

(print (count^ aexp1))
;0

