The idea is that you can put in a string, say "1 + 2 - 6", have the interpreter translate it to lisp. All operators have same precidence, left to right. You can also force certain parts to be evaluated together, via "1 + (6 / 3)"
Here is code for the infix interpreter.
Code: Select all
(defun infix-interpreter (string)
(eval
(infix-to-postfix
(with-input-from-string (stream string)
(let (elts)
(labels ((read-collect ()
(let ((elt (read stream nil nil)))
(if elt (push elt elts)))))
(while (read-collect))
(reverse elts)))))))
(defun infix-to-postfix (list)
(labels ((transform (list)
(if (or (atom (car list))
(not (equal (caar list) (second list))))
(list (second list) (first list) (third list))
(append (first list) (cddr list))))
(element-transform (elt)
(if (listp elt)
(expression elt)
elt))
(expression (list)
(cond ((>= (length list) 3)
(multiple-value-bind (exp rest) (split-list list 3)
(let ((trans (transform (list
(first exp)
(second exp)
(element-transform (third exp))))))
(if rest
(expression (cons trans rest))
trans))))
((= (length list) 1)
(car list))
(t
(error (string-concat "Expression ends with \"" (write-to-string (second list)) "\" as operator."))))))
(expression (cons (element-transform (car list)) (cdr list)))))
(defun split-list (list index)
(cond ((and list (> index 0))
(multiple-value-bind (before-list after-list)
(split-list (cdr list) (1- index))
(values (cons (car list) before-list)
after-list)))
((and list (= index 0))
(multiple-value-bind (before-list after-list)
(split-list (cdr list) index)
(values before-list
(cons (car list) after-list))))
(t
(values nil nil))))
(defmacro while (test &rest body)
`(do ()
((not ,test))
,@body))
Maybe then, for a local var, you could do #let(x 26) {1 + x} becomes (let ((x 26)) (+ 1 x))). The call could embrace the rest of the file. So #let(x 22) without the brackets could translate to (let ((x 22))
.....rest of file here.....
)
Comma separators would allow infix notation within the function call argument list. #/ (1 + 2, 5 - 6 + 3, f)
So let could also be #let(a, 15 + x)
Anyway, seems like it would be cool for user configuration files.
Any feedback, from code critique, to snippit sketches, to ideas about the structure of how things can work, to anything that gets us thinking would be awsome.