Home

Awesome

CI License GitHub code size in bytes

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

  1. Clone or download the latest version from GitHub.
  2. In the cloned directory, run (ql:register-local-projects).
  3. Now you can use (ql:quickload :polisher) anywhere.

ASDF

  1. Clone or download the latest version from GitHub.
  2. Place the directory where your ASDF system can find.
  3. Run (asdf:load-system :polisher).

Requirements

Default operators

Following operators are defined by default:

symbolfunctionpriorityleft associative
++1t
--1t
**2t
//2t
**expt3nil

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.

License

MIT

Author

mrcdr