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

Last change on this file since 4413 was 4413, checked in by Marek Rychlik, 8 years ago

* empty log message *

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