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@ 4420

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

* empty log message *

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