parser top-level property
A mathematical expression parser supporting arithmetic, functions, and variables.
Evaluates expressions using standard operator precedence: parentheses,
function calls, exponentiation (^), multiplication/division (*, /),
and addition/subtraction (+, -).
Returns an Expression AST node that can be evaluated against a variable map.
For example:
final result = parser.parse('3 * (x + 2) ^ 2');
final expression = result.value;
print(expression.eval({'x': 4})); // 108.0
Implementation
final parser = () {
final builder = ExpressionBuilder<Expression>();
builder
// Numbers
..primitive(
seq3(
digit().plus(),
seq2(char('.'), digit().plus()).optional(),
seq3(pattern('eE'), anyOf('+-').optional(), digit().plus()).optional(),
).flatten(message: 'number expected').trim().map(_createValue),
)
// Constant, variables, and functions
..primitive(
seq2(
seq2(
letter(),
word().starString(),
).flatten(message: 'name expected').trim(),
builder.loopback
.starSeparated(char(',').trim())
.map((list) => list.elements)
.skip(before: char('(').trim(), after: char(')').trim())
.optionalWith(const <Expression>[]),
).map2((name, args) => _createBinding(name, args)),
);
// Parentheses (highest precedence wrapper)
builder.group().wrapper(
char('(').trim(),
char(')').trim(),
(left, value, right) => value,
);
// Unary prefix operators (+, -)
builder.group()
..prefix(char('+').trim(), (op, a) => a)
..prefix(char('-').trim(), (op, a) => Application('-', [a], (x) => -x));
// Exponentiation (right-associative)
builder.group().right(
char('^').trim(),
(a, op, b) => Application('^', [a, b], math.pow),
);
// Multiplicative operators (*, /, left-associative)
builder.group()
..left(
char('*').trim(),
(a, op, b) => Application('*', [a, b], (x, y) => x * y),
)
..left(
char('/').trim(),
(a, op, b) => Application('/', [a, b], (x, y) => x / y),
);
// Additive operators (+, -, left-associative)
builder.group()
..left(
char('+').trim(),
(a, op, b) => Application('+', [a, b], (x, y) => x + y),
)
..left(
char('-').trim(),
(a, op, b) => Application('-', [a, b], (x, y) => x - y),
);
return resolve(builder.build()).end();
}();