chainr
chainr combinator parses one or more occurrences of parser, separated by op (in EBNF notation: parser (op parser)*). Returns a value obtained by a recursive right-associative application of fn to the operand values and the values returned by op. It is the right-associative counterpart of chainl, useful for right-associative operators like exponentiation.
Note that the op parser matches only the operator, and fn receives the operand values on both sides of it. Where chainl folds each pair as it reads it, chainr collects the whole run first and folds it afterwards, since the rightmost pair has to be reduced before the ones to its left.
The expressions guide covers precedence, associativity and building a tree rather than a value.
Usage
const Integer = map(regexp(/\d+/g, 'integer'), Number)
const Parser = chainr(
Integer,
string(' ^ '),
(left, _, right) => Math.pow(left, right)
)Success
run(Parser).with('2 ^ 3 ^ 2')
{
isOk: true,
start: 0,
end: 9,
pos: 9,
value: 512
}The input is parsed right-associatively, i.e. as 2 ^ (3 ^ 2) = 2 ^ 9 = 512, and not as (2 ^ 3) ^ 2 = 64.