TL-DR; There is no formal grammar, because it does not exist. The formal specification is the binary encoding. All CPU manufactures document the binary encoding. The specific assembler syntax/grammar is left to tool creators to invent.
There are accepted forms of the encoding. For instance register direct and different operand checks that need to be made. Some instructions have multiple encodings (map to multiple binary values that compute similar results) and this can be used by forensics to see what tools were used. Often different assemblers (ARM corp as
versus Gnu ARM as
) will have support for slightly different notations for operands. In order to circumvent this, people often use the 'C' pre-processor to translate generic assembly to a target assembler using conditional substitution.
There are not usually formal grammars for assembler because they are so simple. It is like a goto program. All loop constructs do not exist in assembler. So everything is very linear. It might have a 'lex' (or syntax) type file of accepted mnemonics and pseudo-instructions, but instructions can be put in any order without an assembler complaining (although it may crash due to garbage register values).
The general documentation is just a mnemonic with a binary encoding. The encoding is simple because the hardware (CPU) just examines certain bits to determine the form. For instance, ALU instructions:
ADD
- add and don't set condition codes
SUB
- subtract and don't set condition codes
ADDS
- add and set condition codes
SUBS
- subtract and set condition codes.
They have two source registers (R0-R15 are candidates) and one destination (R0-R15). So that typically takes 12bits of 32bits. The ARM has a 'conditional execution' portion that uses four bits. The assembler just needs to select the leading portion (instruction type) and stuff the remaining bits of the operands. It is the same for all architectures. The issue comes with labels, where you need to compute offsets from one instruction to another. This is the main job of an assembler. Otherwise, it is a one-to-one mapping/translation and there is only a very limited grammar.
Related: Pre-processor as an assembler