- (cond
- ((not lexed-ast) nil)
- ((numberp (car lexed-ast)) (cons (coerce (car lexed-ast) 'double-float) (parse (cdr lexed-ast))))
- ((eql :[ (car lexed-ast)) (parse-block (cdr lexed-ast)))
- ((and (symbolp (car lexed-ast)) (find-prim (car lexed-ast)))
- (let*
- ((prim (find-prim (car lexed-ast)))
- (num-args (prim-num-args prim))
- (parsed-remainder (parse (cdr lexed-ast))))
- (cons
- (cons
- (prim-name prim)
- (mapcar
- #'help-arg
- (prim-args prim)
- (butlast parsed-remainder (- (length parsed-remainder) num-args))))
- (nthcdr num-args parsed-remainder))))
- (t (error "Couldn't parse ~S" lexed-ast))))
+ (let
+ ; could have defined this using the special variable, but didn't to make the
+ ; function definition simpler, as well as the documentation.
+ ((*dynamic-prims* dynamic-prims))
+ (parse-internal lexed-ast)))
+
+(defun parse-internal (lexed-ast &key prev-item arg-countdown)
+ (let
+ ((prim (and lexed-ast (symbolp (car lexed-ast)) (find-prim (car lexed-ast)))))
+ (cond
+ ((and arg-countdown (zerop arg-countdown)) (append (when prev-item (list prev-item)) lexed-ast))
+ ((and prim (prim-is-infix prim))
+ (parse-prim prim lexed-ast prev-item arg-countdown)) ; Special casing infix prims is cleaner
+ (t
+ (append
+ (when prev-item (list prev-item))
+ (cond
+ ((not lexed-ast) nil)
+ ((stringp (car lexed-ast))
+ (parse-internal (cdr lexed-ast)
+ :prev-item (car lexed-ast)
+ :arg-countdown (when arg-countdown (1- arg-countdown))))
+ ((numberp (car lexed-ast))
+ (parse-internal (cdr lexed-ast)
+ :prev-item (coerce (car lexed-ast) 'double-float)
+ :arg-countdown (when arg-countdown (1- arg-countdown))))
+ ((eql (intern "(" (find-package :keyword)) (car lexed-ast)) (parse-parened-expr (cdr lexed-ast) arg-countdown))
+ ((eql (intern ")" (find-package :keyword)) (car lexed-ast)) (error "Closing parens has no opening parens"))
+ ((eql :[ (car lexed-ast)) (parse-block (cdr lexed-ast) arg-countdown))
+ (prim
+ (when (prim-structure-prim prim)
+ (error "This doesn't make sense here"))
+ (parse-prim prim lexed-ast nil arg-countdown))
+ (t (error "Couldn't parse ~S" lexed-ast))))))))
+
+(defun parse-prim (prim lexed-ast prev-item arg-countdown)
+ (let*
+ ((num-args (- (prim-num-args prim) (if (prim-is-infix prim) 1 0)))
+ (half-parsed-remainder (parse-internal (cdr lexed-ast) :arg-countdown num-args)))
+ (parse-internal
+ (nthcdr num-args half-parsed-remainder)
+ :arg-countdown (when arg-countdown (if (prim-is-infix prim) arg-countdown (1- arg-countdown)))
+ :prev-item
+ (cons
+ (prim-name prim)
+ (mapcar
+ #'help-arg
+ (prim-args prim)
+ (append
+ (when (prim-is-infix prim) (list prev-item))
+ (butlast half-parsed-remainder (- (length half-parsed-remainder) num-args))))))))