polisher
2021-12-30
Infix notation to S-expression translator
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.