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

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