Just pattern-based macros that recognize outermost operators should work too like this example. Afterwards, replace printf-reverse by calls to some infix-to-postfix conversion algorithm and use the op struct to identify operators.
#lang racket/base
(struct op (sym) #:transparent)
(define-syntax mark-$-ops
(syntax-rules (+ - * /)
[(_ () (e-acc ...))
(list e-acc ...)]
[(_ (+ e ...) expr-acc) (mark-$-ops (e ...) ((op '+) . expr-acc))]
[(_ (- e ...) expr-acc) (mark-$-ops (e ...) ((op '-) . expr-acc))]
[(_ (* e ...) expr-acc) (mark-$-ops (e ...) ((op '*) . expr-acc))]
[(_ (/ e ...) expr-acc) (mark-$-ops (e ...) ((op '/) . expr-acc))]
[(_ (expr0 e ...) expr-acc) (mark-$-ops (e ...) (expr0 . expr-acc))]))
(define-syntax $
(syntax-rules ()
[(_ e ...)
(printf "TODO: parse and convert to postfix\n~a\n"
(reverse (mark-$-ops (e ...) ())))]))
(define y 456)
(define (compute x)
(let ([z 7])
($ x + 3 * y + z / 2)))
(compute 9)
Here is the result of macro expansion displayed in the macro stepper:
