File: mathtran.l

package info (click to toggle)
euslisp 9.31%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,448 kB
  • sloc: ansic: 41,610; lisp: 3,339; makefile: 286; sh: 238; asm: 138; python: 53
file content (141 lines) | stat: -rw-r--r-- 4,527 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
;;;;	mathtran.l
;;;;	convert C-like arithmethic expressions into lisp notation.
;;;;	1987-Sep
;;;;	Copyright (c) 1987,
;;;;	Toshihiro MATSUI, Electrotechnical Laboratory
;;;;	Tsukuba-city, Ibaraki, 305 JAPAN

(in-package "LISP")

#+:kcl
(defmacro while (cond &rest body)
   `(do ()
        ((not ,cond))
	. ,body))
#+:kcl
(defun memq (x l) (member x l :test #'eq))

(defun expression (exp &optional (lhs nil) &aux result letvar-alist)
  (labels
     (
      (letvar (form)
	   (let ((v (assoc form letvar-alist :test #'equal)))
		(cond (v (incf (third v)) (second v))
		      (t (setf v (gensym))
			 (push (list form v 1) letvar-alist)
			 v))))
      (factor1 (exp)
	(let* ((sy (pop exp)) (arglist) form)
	   (cond
	     ((consp sy)
		(multiple-value-setq (sy form) (expr sy))
		(if form (error "illegal math expression for % macro"))
		(values sy exp))
	     ((consp (first exp))	;function call or array ref.
		(setf arglist (pop exp))
		(cond ((eq (first arglist) 'aref)
		        (setf arglist (expr-list (rest arglist)))
			(setf form (cons 'aref (cons sy arglist)))
			(unless lhs (setf form (letvar form)))
			(values form exp))
		      (t
			(values (letvar (cons sy (expr-list arglist))) exp) )) )
	     (t (values sy exp)))))
      (factor (exp)
	(let* ((left) (right) (form))
	   (multiple-value-setq (left exp) (factor1 exp))
	   (cond
	      ((eq (first exp) '**)
		(multiple-value-setq (right exp) (factor1 (rest exp)))
		(cond
		   ((and (integerp right) (< right 10))
		    (setf form (list '*))
		    (cond ((atom left) 
			    (dotimes (i right) (nconc form (list left)))
			    (values (letvar form) exp))
			  (t 
			   (dotimes (i right) (nconc form (list 'temp)))
			    (values `(let ((temp ,left)) ,form) exp))))
	  	   (t	(values (list 'expt left right) exp))))
	      ((numberp left) (values left exp))
	      (t (values left exp) ))) )
      (term (exp)
	  (let* ((left) (op) (right))
	    (multiple-value-setq (left exp) (factor exp))
	    (setf op (first exp))
	    (cond
		((memq op '(* /))
		 (while (memq op '(* /))
		    (setf left (list op left))
		    (while (eq (first exp) op)
		       (multiple-value-setq (right exp) (factor (rest exp)))
		       (nconc left (list right))   )
		    (setf op (first exp)))
		 (values left exp))
		(t (values left exp)))))
      (expr (exp)
	  (let* ((op (first exp)) (left) (right))
	    (if (memq op '(+ -))	;+- as unary operator
		(setf  exp (rest  exp)))
	    (multiple-value-setq (left exp) (term exp))
	    (if (eq op '-)
		(setf left (list op  left)))
	    (when (memq (first exp) '(+ -))
		 (setf left (list '+ left))
	         (while (memq (setf op (first exp)) '(+ -))
		     (multiple-value-setq (right exp) (term (rest exp)))
		     (if (eq op '-) (setf right (list '- right)))
		     (nconc left (list right))))
	     (values left exp)))
      (expr-list (exp)
	  (let (temp result)
	    (while exp
		(multiple-value-setq (temp exp) (expr exp))
		(push temp result))
	    (nreverse result)))
      (rel-expr (exp)
	  (let ((left) (op) (right))
	    (multiple-value-setq (left exp) (expr exp))
	    (setf op (pop exp))
	    (when (memq op '(== != /= < >  <= >=))
		(multiple-value-setq (right exp) (expr exp))
	        (setf left
		    (list (second (assoc op '((== =) (!= /=) (/= /=) (< <)
					      (<= <=) (> >) (>= >=))))
		          left right)))
	    (values left exp)))	
      (reconstruct-form (exp)
        (setf exp (list exp))
	(let ((letpairs))
	   (dolist (lv  letvar-alist)
	      (if (> (third lv) 1)	;referenced more than once
		  (push (list (second lv) (first lv)) letpairs)
		  (nsubst (first lv) (second lv) exp)))
	   (if letpairs
	       `(let* ,letpairs  . ,exp)
	       (first exp)))))
   (multiple-value-setq (result exp) (rel-expr exp))
   (if exp (error "illegal expression in % macro"))
   (reconstruct-form result) ))

(defun infix2prefix (file &optional char)
  (let ((exp (read file)))
     (cond
	((symbolp exp)	;probably a left-hand-side array ref.
	 (expression (list exp (read file)) t))
	((eq (second exp) '=)
	 (list 'setq (car exp) (expression (cddr exp) nil)))
	((eq (third exp) '=)
	 (list 'setf (expression (list (first exp) (second exp)) t)
		     (expression (cdddr exp) nil)))
        (t  (expression exp nil)))) ) )

(defun read-aref (file &optional char)
   (cons 'aref (read-delimited-list #\] file)))

(set-macro-character #\% 'infix2prefix)
(set-macro-character #\[ 'read-aref)
(set-syntax-from-char #\] #\))

(provide :mathtran "@(#)$Id: mathtran.l,v 1.1.1.1 2003/11/20 07:46:31 eus Exp $")