There is some level of text processing to assemble into object files. I imagine it wasn't a stretch to include built-in and user-defined macros on top of that. It's still architecture dependent because it is so close to machine code as you say but I think there is a bit of wiggle room for convenience features. If you notice, assemblers have varying syntax from assembler to assembler. Code written for gas is different from nasm, etc. With some assemblers, the difference is minimal but enough to catch you out, such as literals, referencing memory, etc.
I think with GNU in particular it uses at&t syntax by default (though accepts Intel too). With that, the order of operands are reversed so typically, with Intel as common, you have:
Where, with at&t, you have:
They do the same thing. Both add 2 to whatever's in the eax reg.