close Warning: Can't synchronize with repository "(default)" (The repository directory has changed, you should resynchronize the repository with: trac-admin $ENV repository resync '(default)'). Look in the Trac log for more information.

source: branches/f4grobner/infix-printer.lisp@ 4418

Last change on this file since 4418 was 4418, checked in by Marek Rychlik, 9 years ago

* empty log message *

File size: 6.0 KB
Line 
1;;; -*- Mode: Lisp -*-
2#|
3 *--------------------------------------------------------------------------*
4 | Copyright (C) 1994, Marek Rychlik (e-mail: rychlik@math.arizona.edu) |
5 | Department of Mathematics, University of Arizona, Tucson, AZ 85721 |
6 | |
7 | Everyone is permitted to copy, distribute and modify the code in this |
8 | directory, as long as this copyright note is preserved verbatim. |
9 *--------------------------------------------------------------------------*
10|#
11
12(defpackage "INFIX-PRINTER"
13 (:use "COMMON-LISP"
14 "INFIX" ;for operator-lessp
15 )
16 (:export infix-print infix-print-to-string infix-print-to-stream))
17
18(in-package "INFIX-PRINTER")
19
20(proclaim '(optimize (speed 0) (space 0) (safety 3) (debug 3)))
21
22(defun infix-print-separated-list (lst sep stream op print-level
23 &optional
24 (alt-op nil)
25 (alt-sep alt-op)
26 &aux
27 (beg t)
28 (count 0)
29 true-op
30 true-sep)
31 "Print a list LST using SEP as separator, to stream STREAM. Every
32argument is printed usin OP as main operator. PRINT-LEVEL is used to
33control printing nested expressions as expected: subexpressions at
34level exceeding PRINT-LEVEL are printed as ellipsis. The argument BEG
35indicates whether this is the start of a sequence of arguments with
36the main operator OP. The argument ALT-OP, if not NIL, replaces
37operator OP for list elements beyond the first one. Similarly, ALT-SEP
38replaces SEP for list elements beyond the first one."
39
40 (cond
41 ((endp lst) nil)
42
43 ;; Handle *print-level*
44 ((and (numberp *print-level*)
45 (> print-level *print-level*))
46 (format stream "#"))
47
48 (t
49 (dolist (arg lst)
50 ;;(format t "Processing arg: ~S~%" arg)
51 (setf true-op op
52 true-sep sep)
53
54 (incf count)
55
56 ;; The following code handles unary minus
57 ;; Thus:
58 ;; (+ x (- y z)) --> X + Y - Z
59 ;; (+ x (- y)) --> X - Y
60 (when (and alt-op
61 (> count 1)
62 (consp arg)
63 (endp (cddr arg))
64 (eq alt-op (car arg)))
65 (psetf arg (cadr arg)
66 true-op (car arg)
67 alt-sep nil)
68 ;;(format t "Arg changed: ~S, true-sep: ~S~%" arg true-sep)
69 )
70
71
72 (cond
73 (beg
74 (setf beg nil))
75 (t
76 (format stream "~a" true-sep)))
77
78 ;; If *print-length* exceeded, print ellipsis
79 (when (and (numberp *print-length*) (> count *print-length*))
80 (format stream "...")
81 (return-from infix-print-separated-list (values)))
82
83 (infix-print arg stream true-op print-level))))
84 (values))
85
86(defun infix-print-arg-list (lst stream print-level)
87 "Print a comma-separated list."
88 (infix-print-separated-list lst '\, stream '\, print-level))
89
90(defun infix-print-to-stream (expr &optional (stream t) (op nil) (print-level 0))
91 "Print an expression EXPR in infix notation to stream STREAM.
92If OP is not nil, the expression is parenthesized if its operator
93has lower precedence than OP. Returns (VALUES)."
94 (cond
95 ;; Handle *print-level*
96 ((and (numberp *print-level*)
97 (> print-level *print-level*))
98 (format stream "#"))
99
100 ;; Null expression is an error
101 ((null expr)
102 (error "Null expression."))
103
104 ;; Atoms are printed using ~A format directive
105 ((atom expr)
106 (format stream "~a" expr))
107
108 ;; Check if the operator of this expression has lower precedence
109 ;; than the surrounding operator, and parenthesize if necessary
110 ((and op
111 (operator-lessp (car expr) op))
112 (format stream "(")
113 (infix-print expr stream nil (1+ print-level))
114 (format stream ")"))
115
116 ;; Unary minus needs special handling
117 ((and (eq (car expr) '-) (endp (cddr expr)))
118 (format stream "-")
119
120 ;; Print the second element in product context
121 (infix-print (cadr expr) stream '* (1+ print-level)))
122
123 ;; All other operators
124 (t
125 (case (car expr)
126
127 ;; Arithmetic operators
128 ((+ - * /)
129 (infix-print-separated-list
130 (cdr expr)
131 (car expr)
132 stream
133 (car expr)
134 (1+ print-level)
135 (cond ((eq (car expr) '+) '-)
136 ((eq (car expr) '-) '-)
137 ((eq (car expr) '*) '/)
138 ((eq (car expr) '/) '/)
139 (t nil))))
140
141 ;; Exponentials
142 (expt
143 (unless (= (length (cdr expr)) 2)
144 (error "expt must take 2 arguments."))
145 (infix-print-separated-list
146 (cdr expr)
147 '^
148 stream
149 '^
150 (1+ print-level)))
151
152 ;; Assuming function call
153 (otherwise
154 (cond
155
156 ;; Handle array references
157 ((eq (car expr) 'aref)
158 ;; Special syntax for subscripted variables
159 ;; consistent with the infix package.
160 (format stream "~a[" (cadr expr))
161 (infix-print-separated-list (cddr expr) '\, stream '\, (1+ print-level))
162 (format stream "]"))
163
164 ;; Handle lists
165 ((and (symbolp (car expr))
166 (string= (symbol-name (car expr)) "["))
167 (format stream "[")
168 (infix-print-separated-list (cdr expr) '\, stream '\, (1+ print-level))
169 (format stream "]"))
170
171 ;; Handle generic function call syntax
172 (t
173 (format stream "~a(" (car expr))
174 (infix-print-arg-list (cdr expr) stream (1+ print-level))
175 (format stream ")")))))))
176 (values))
177
178(defun infix-print-to-string (expr &optional (op nil) (print-level 0)
179 &aux (fstr (make-array '(0) :element-type 'base-char
180 :fill-pointer 0 :adjustable t)))
181 "Print an expression EXPR in infix notation to a string. If OP is
182not nil, the expression is parenthesized if its operator has lower
183precedence than OP. Returns the string containing the printed
184expression."
185 (with-output-to-string (s fstr)
186 (infix-print-to-stream expr s op print-level))
187 fstr)
188
189(defun infix-print (expr &optional (stream t) (op nil) (print-level 0))
190 "Print an expression EXPR in infix notation to stream STREAM or to
191string if (NULL STREAM). If OP is not nil, the expression is
192parenthesized if its operator has lower precedence than OP. Returns
193the string containing the printed expression, or (VALUES) if (NULL
194STREAM) is true."
195 (cond
196 ((null stream)
197 (infix-print-to-string expr op print-level))
198 (t (infix-print-to-stream expr stream op print-level))))
Note: See TracBrowser for help on using the repository browser.