Awesome
Polisher
Infix notation to S-expression (Polish notation) translator for Common Lisp
Overview
Formulae inside the reader macro #i{ ... }
are interpreted as infix notation.
If you don't want to use it, the macro polish
is available instead.
(polisher:activate-infix-syntax) ; Activate #i{ ... } reader macro
#i{1+2*3}
;=> 7
(polisher:polish "1+2*3") ; Exactly the same as the above one
;=> 7
#i{1 + 2*3} ; Spaces can be inserted anywhere
;=> 7
#i{2*3/4}
;=> 3/2
#i{2**2**3} ; Identical to 2**(2**3), not (2**2)**3
;=> 256
#i{atan(1.0d0, 1.0d0)}
;=> 0.7853981633974483d0
(flet ((add1 (x) (+ x 1)))
#i{add1(2)+3})
;=> 6
(defparameter *some-global-value* 1.5) ; The symbol containg operator charcters
#i{1 + 2 * "*some-global-value*"} ; must be double-quoted
;=> 4.0
#i{2*#c(1 2)+3}
;=> #C(5 4)
#i{#b101 +3} ; Some spaces are needed after #b101
;=> 8
Installation
Quicklisp
If you already have Quicklisp client, just run the following:
(ql:quickload :polisher)
It will resolve dependencies automatically.
Github and Quicklisp
- Clone or download the latest version from GitHub.
- In the cloned directory, run
(ql:register-local-projects)
. - Now you can use
(ql:quickload :polisher)
anywhere.
ASDF
- Clone or download the latest version from GitHub.
- Place the directory where your ASDF system can find.
- Run
(asdf:load-system :polisher)
.
Requirements
Default operators
Following operators are defined by default:
symbol | function | priority | left associative |
---|---|---|---|
+ | + | 1 | t |
- | - | 1 | t |
* | * | 2 | t |
/ | / | 2 | t |
** | expt | 3 | nil |
Add your own operator
(polisher:add-operator (make-instance 'polisher:operator
:symbol '^
:function 'expt
:priority 3
:left-associative nil))
#i{2^2^3}
;=> 256
Note that if there are left-associative operators and right-associative operators
both having the same priority, formulae can't be evaluated correctly.
For example, when op1
is left-associative and op2
is right-associative,
x op1 y op2 z
can be interpreted as either (x op1 y) op2 z
and
x op1 (y op2 z)
.
When you add your own operator, be careful of which package its symbol is interned in.
Restrictions
Symbols start with numbers
Symbols which start with numbers must be double-quoted. The following example shows the reason:
(let ((1e 2))
#i{1e+1+1})
;=> 11.0
(let ((1e 2))
#i{"1e"+1+1})
;=> 4
No one defines such an odd symbol? Remember the standard functions 1+
and 1-
!
Symbols with vertical bars
Symbols whose symbol-name sandwiched in vertical bars (e.g. |ab de|
) can't be used.
This is because someone may want to use a vertical bar as the logical OR operator.
Double-quoting is necessary?
The infix formula 1+*global-symbol*
can be uniquely interpreted as (+ 1 *global-symbol*)
,
so double-quoting may be unnecessary.
However in my opinion, the formula seems very weird when it appears in ALGOL-like languages;
so I think double-quoting should be used.
In addition, many text editors highlight double-quoted things, helping us to distinguish
symbol-names from operators.