A grammar establishes the pattern of strings that make up a language. You can think of a grammar running forward, generating strings, or running backward, recognizing strings. Equivalent grammars may recognize the same strings in different orders.
This means that you can use a grammar to specify the order in which to recognize operators, and that in turn lets you control precedence and associativity.
Once you have a grammar that recognizes the strings of your language in the right order, you must consider potential infinite loops when you implement the grammar with a parser. You can remove left recursion in the grammar by transforming it to an equivalent grammar that recognizes the same strings in the same order, but without using left recursion. After removing left recursion, you must manage the presence of cycles in the grammar, initializing variables to avoid cyclic definitions in a parser's code.