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

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

* empty log message *

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