Recursive descent parsers have trouble with left-associative operators if you only allow recursion. But if you allow iteration, you can build up the parse tree while iterating through terms at the same precedence level. For example, this defines + and - as left-associative at the same precedence level:
// EBNF is SUM = PRODUCT , { ("+" | "-") , PRODUCT }
AstNode *parseSum()
{
if (auto lhs = parseProduct()) {
while (1) {
if (consume(T_PLUS)) {
if (auto rhs = parseProduct()) { // You'd call parseSum instead to get right associativity
lhs = mkAst(A_add, lhs, rhs); // Instead, left associativity happens here
}
else {
return nullptr;
}
}
else if (consume(T_MINUS)) {
if (auto rhs = parseProduct()) {
lhs = mkAst(A_sub, lhs, rhs);
}
else {
return nullptr;
}
}
else {
return lhs;
}
}
}
else {
return nullptr;
}
}
As a bonus, it doesn't blow out your stack when parsing long expressions.Very few binary operators should be right-associative. Basically just ?: and = .