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

Last change on this file since 4414 was 4414, 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-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 ;; This is to handle unary minus and unary division.
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 (setf arg (cadr arg)
66 true-sep alt-sep)
67 )
68
69
70 (if beg
71 (setf beg nil)
72 (format stream "~a" true-sep))
73
74 ;; If *print-length* exceeded, print ellipsis
75 (when (and (numberp *print-length*) (> count *print-length*))
76 (format stream "...")
77 (return-from infix-print-separated-list (values)))
78
79 (infix-print-to-stream arg stream true-op print-level))))
80 (values))
81
82(defun infix-print-arg-list (lst stream print-level)
83 "Print a comma-separated list."
84 (infix-print-separated-list lst '\, stream '\, print-level))
85
86(defun infix-print-to-stream (expr &optional (stream t) (op nil) (print-level 0))
87 "Print an expression EXPR in infix notation to stream STREAM.
88If OP is not nil, the expression is parenthesized if its operator
89has lower precedence than OP. Returns (VALUES)."
90 (cond
91 ;; Handle *print-level*
92 ((and (numberp *print-level*)
93 (> print-level *print-level*))
94 (format stream "#"))
95
96 ;; Null expression is an error
97 ((null expr)
98 (error "Null expression."))
99
100 ;; Atoms are printed using ~A format directive
101 ((atom expr)
102 (format stream "~a" expr))
103
104 ;; Check if the operator of this expression has lower precedence
105 ;; than the surrounding operator, and parenthesize if necessary
106 ((and op
107 (operator-lessp (car expr) op))
108 (format stream "(")
109 (infix-print expr stream nil (1+ print-level))
110 (format stream ")"))
111
112 ;; Unary minus needs special handling
113 ((and (eq (car expr) '-) (endp (cddr expr)))
114 (format stream "-")
115 ;; Print the second element in product context
116 (infix-print (cadr expr) stream '* (1+ print-level)))
117
118 ;; All other operators
119 (t
120 (case (car expr)
121
122 ;; Arithmetic operators
123 ((+ - * /)
124 (infix-print-separated-list
125 (cdr expr)
126 (car expr)
127 stream
128 (car expr)
129 (1+ print-level)
130 (cond ((eq (car expr) '+) '-)
131 ((eq (car expr) '-) '-)
132 ((eq (car expr) '*) '/)
133 ((eq (car expr) '/) '/)
134 (t nil))))
135
136 ;; Exponentials
137 (expt
138 (unless (= (length (cdr expr)) 2)
139 (error "expt must take 2 arguments."))
140 (infix-print-separated-list
141 (cdr expr)
142 '^
143 stream
144 '^
145 (1+ print-level)))
146
147 ;; Assuming function call
148 (otherwise
149 (cond
150
151 ;; Handle array references
152 ((eq (car expr) 'aref)
153 ;; Special syntax for subscripted variables
154 ;; consistent with the infix package.
155 (format stream "~a[" (cadr expr))
156 (infix-print-separated-list (cddr expr) '\, stream '\, (1+ print-level))
157 (format stream "]"))
158
159 ;; Handle lists
160 ((and (symbolp (car expr))
161 (string= (symbol-name (car expr)) "["))
162 (format stream "[")
163 (infix-print-separated-list (cdr expr) '\, stream '\, (1+ print-level))
164 (format stream "]"))
165
166 ;; Handle generic function call syntax
167 (t
168 (format stream "~a(" (car expr))
169 (infix-print-arg-list (cdr expr) stream (1+ print-level))
170 (format stream ")")))))))
171 (values))
172
173(defun infix-print-to-string (expr &optional (op nil) (print-level 0)
174 &aux (fstr (make-array '(0) :element-type 'base-char
175 :fill-pointer 0 :adjustable t)))
176 "Print an expression EXPR in infix notation to a string. If OP is
177not nil, the expression is parenthesized if its operator has lower
178precedence than OP. Returns the string containing the printed
179expression."
180 (with-output-to-string (s fstr)
181 (infix-print-to-stream expr s op print-level))
182 fstr)
183
184(defun infix-print (expr &optional (stream t) (op nil) (print-level 0))
185 "Print an expression EXPR in infix notation to stream STREAM or to
186string if (NULL STREAM). If OP is not nil, the expression is
187parenthesized if its operator has lower precedence than OP. Returns
188the string containing the printed expression, or (VALUES) if (NULL
189STREAM) is true."
190 (cond
191 ((null stream)
192 (infix-print-to-string expr op print-level))
193 (t (infix-print-to-stream expr stream op print-level))))
Note: See TracBrowser for help on using the repository browser.