I suggest going with Unicode terminology and conventional predicates: ascii-open-punctuation?, ascii-close-punctuation?, and ascii-mirroring-character. Not quite as terse, perhaps, but more familiar.
I've thought of adding:
(ascii-opening-bracket char) => char or #f
(ascii-closing-bracket char) => char or #f
(ascii-opposing-bracket char) => opposing-char or #f
If char is one of ( [ { < then ascii-opening-bracket returns that same
char, otherwise it returns #f. For those same chars
ascii-opposing-bracket returns ) ] } > or #f respectively.
If char is one of ) ] } > then ascii-closing-bracket returns that same
char, otherwise it returns #f. For those same chars
ascii-opposing-bracket returns ( [ { < or #f respectively.
I've wished for procedures like these when writing parsers a couple of
times. Would this be too fancy? You can write code like this:
(if (ascii-opening-bracket char)
(read-delimited-list (ascii-opposing-bracket char)))