https://github.com/ruby/ruby/blob/trunk/parse.y
https://github.com/clojure/tools.reader/blob/master/src/main...
An S-Expression parser will accept (loop for in do), and the rest of the language implementation has to deal with detecting that there is no variable, no collection and no action.
S-expressions know nothing and represent nothing about concepts like functions, variables, argument lists, operators, bindings, type declarations, function defintions, variable defintions, class definitions, ...
Even syntactic (3 4 +) is READ successfully, but it is not a valid Clojure form.
Basically a READER is on the level of a TOKENIZER, but not a parser.
(2 + 3)
(- 3 4)
All are valid s-expressions. Only one is a valid Lisp expression.
When we parse an expression, we usually parse a textual representation into an object. If the object is meant / subject to evaluation -> then we call this a form.
Every character in a S-expression must be "dealt with at the reader level" (and produced at the printer level).
The term "S-expression" was originally in contrast with "M-expression", but that's a historic usage.