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

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

* empty log message *

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