| Index: packages/petitparser/lib/src/petitparser/expression.dart
|
| diff --git a/petitparser/lib/src/core/expression.dart b/packages/petitparser/lib/src/petitparser/expression.dart
|
| similarity index 51%
|
| rename from petitparser/lib/src/core/expression.dart
|
| rename to packages/petitparser/lib/src/petitparser/expression.dart
|
| index e71de7e7911adacc2f92f11aceb6fded81b9fb22..80b4f06915731201dc92eb4a146f7df1b1dbe414 100644
|
| --- a/petitparser/lib/src/core/expression.dart
|
| +++ b/packages/petitparser/lib/src/petitparser/expression.dart
|
| @@ -1,96 +1,84 @@
|
| part of petitparser;
|
|
|
| -/**
|
| - * A builder that allows the simple definition of expression grammars with
|
| - * prefix, postfix, and left- and right-associative infix operators.
|
| - *
|
| - * The following code creates the empty expression builder:
|
| - *
|
| - * var builder = new ExpressionBuilder();
|
| - *
|
| - * Then we define the operator-groups in descending precedence. The highest
|
| - * precedence have the literal numbers themselves:
|
| - *
|
| - * builder.group()
|
| - * ..primitive(digit().plus()
|
| - * .seq(char('.').seq(digit().plus()).optional())
|
| - * .flatten().trim().map((a) => double.parse(a)));
|
| - *
|
| - * Then come the normal arithmetic operators. Note, that the action blocks receive
|
| - * both, the terms and the parsed operator in the order they appear in the parsed
|
| - * input.
|
| - *
|
| - * // negation is a prefix operator
|
| - * builder.group()
|
| - * ..prefix(char('-').trim(), (op, a) => -a);
|
| - *
|
| - * // power is right-associative
|
| - * builder.group()
|
| - * ..right(char('^').trim(), (a, op, b) => math.pow(a, b));
|
| - *
|
| - * // multiplication and addition is left-associative
|
| - * builder.group()
|
| - * ..left(char('*').trim(), (a, op, b) => a * b)
|
| - * ..left(char('/').trim(), (a, op, b) => a / b);
|
| - * builder.group()
|
| - * ..left(char('+').trim(), (a, op, b) => a + b)
|
| - * ..left(char('-').trim(), (a, op, b) => a - b);
|
| - *
|
| - * Finally we can build the parser:
|
| - *
|
| - * var parser = builder.build();
|
| - *
|
| - * After executing the above code we get an efficient parser that correctly
|
| - * evaluates expressions like:
|
| - *
|
| - * parser.parse('-8'); // -8
|
| - * parser.parse('1+2*3'); // 7
|
| - * parser.parse('1*2+3'); // 5
|
| - * parser.parse('8/4/2'); // 2
|
| - * parser.parse('2^2^3'); // 256
|
| - */
|
| +/// A builder that allows the simple definition of expression grammars with
|
| +/// prefix, postfix, and left- and right-associative infix operators.
|
| +///
|
| +/// The following code creates the empty expression builder:
|
| +///
|
| +/// var builder = new ExpressionBuilder();
|
| +///
|
| +/// Then we define the operator-groups in descending precedence. The highest
|
| +/// precedence have the literal numbers themselves:
|
| +///
|
| +/// builder.group()
|
| +/// ..primitive(digit().plus()
|
| +/// .seq(char('.').seq(digit().plus()).optional())
|
| +/// .flatten().trim().map((a) => double.parse(a)));
|
| +///
|
| +/// Then come the normal arithmetic operators. Note, that the action blocks receive
|
| +/// both, the terms and the parsed operator in the order they appear in the parsed
|
| +/// input.
|
| +///
|
| +/// // negation is a prefix operator
|
| +/// builder.group()
|
| +/// ..prefix(char('-').trim(), (op, a) => -a);
|
| +///
|
| +/// // power is right-associative
|
| +/// builder.group()
|
| +/// ..right(char('^').trim(), (a, op, b) => math.pow(a, b));
|
| +///
|
| +/// // multiplication and addition is left-associative
|
| +/// builder.group()
|
| +/// ..left(char('*').trim(), (a, op, b) => a * b)
|
| +/// ..left(char('/').trim(), (a, op, b) => a / b);
|
| +/// builder.group()
|
| +/// ..left(char('+').trim(), (a, op, b) => a + b)
|
| +/// ..left(char('-').trim(), (a, op, b) => a - b);
|
| +///
|
| +/// Finally we can build the parser:
|
| +///
|
| +/// var parser = builder.build();
|
| +///
|
| +/// After executing the above code we get an efficient parser that correctly
|
| +/// evaluates expressions like:
|
| +///
|
| +/// parser.parse('-8'); // -8
|
| +/// parser.parse('1+2*3'); // 7
|
| +/// parser.parse('1*2+3'); // 5
|
| +/// parser.parse('8/4/2'); // 2
|
| +/// parser.parse('2^2^3'); // 256
|
| class ExpressionBuilder {
|
| final List<ExpressionGroup> _groups = new List();
|
|
|
| - /**
|
| - * Creates a new group of operators that share the same priority.
|
| - */
|
| + /// Creates a new group of operators that share the same priority.
|
| ExpressionGroup group() {
|
| var group = new ExpressionGroup();
|
| _groups.add(group);
|
| return group;
|
| }
|
|
|
| - /**
|
| - * Builds the expression parser.
|
| - */
|
| + /// Builds the expression parser.
|
| Parser build() => _groups.fold(
|
| failure('Highest priority group should define a primitive parser.'),
|
| (a, b) => b._build(a));
|
| }
|
|
|
| -/**
|
| - * Models a group of operators of the same precedence.
|
| - */
|
| +/// Models a group of operators of the same precedence.
|
| class ExpressionGroup {
|
|
|
| - /**
|
| - * Defines a new primitive or literal [parser].
|
| - */
|
| + /// Defines a new primitive or literal [parser].
|
| void primitive(Parser parser) {
|
| _primitives.add(parser);
|
| }
|
|
|
| - Parser _build_primitive(Parser inner) {
|
| - return _build_choice(_primitives, inner);
|
| + Parser _buildPrimitive(Parser inner) {
|
| + return _buildChoice(_primitives, inner);
|
| }
|
|
|
| final List<Parser> _primitives = new List();
|
|
|
| - /**
|
| - * Adds a prefix operator [parser]. Evaluates the optional [action] with the
|
| - * parsed `operator` and `value`.
|
| - */
|
| + /// Adds a prefix operator [parser]. Evaluates the optional [action] with the
|
| + /// parsed `operator` and `value`.
|
| void prefix(Parser parser, [action(operator, value)]) {
|
| if (action == null) {
|
| action = (operator, value) => [operator, value];
|
| @@ -98,11 +86,11 @@ class ExpressionGroup {
|
| _prefix.add(parser.map((operator) => new _ExpressionResult(operator, action)));
|
| }
|
|
|
| - Parser _build_prefix(Parser inner) {
|
| + Parser _buildPrefix(Parser inner) {
|
| if (_prefix.isEmpty) {
|
| return inner;
|
| } else {
|
| - return new SequenceParser([_build_choice(_prefix).star(), inner]).map(
|
| + return new SequenceParser([_buildChoice(_prefix).star(), inner]).map(
|
| (tuple) {
|
| return tuple.first.reversed.fold(tuple.last, (value, result) {
|
| return result.action(result.operator, value);
|
| @@ -113,10 +101,8 @@ class ExpressionGroup {
|
|
|
| final List<Parser> _prefix = new List();
|
|
|
| - /**
|
| - * Adds a postfix operator [parser]. Evaluates the optional [action] with the
|
| - * parsed `value` and `operator`.
|
| - */
|
| + /// Adds a postfix operator [parser]. Evaluates the optional [action] with the
|
| + /// parsed `value` and `operator`.
|
| void postfix(Parser parser, [action(value, operator)]) {
|
| if (action == null) {
|
| action = (value, operator) => [value, operator];
|
| @@ -124,11 +110,11 @@ class ExpressionGroup {
|
| _postfix.add(parser.map((operator) => new _ExpressionResult(operator, action)));
|
| }
|
|
|
| - Parser _build_postfix(Parser inner) {
|
| + Parser _buildPostfix(Parser inner) {
|
| if (_postfix.isEmpty) {
|
| return inner;
|
| } else {
|
| - return new SequenceParser([inner, _build_choice(_postfix).star()]).map(
|
| + return new SequenceParser([inner, _buildChoice(_postfix).star()]).map(
|
| (tuple) {
|
| return tuple.last.fold(tuple.first, (value, result) {
|
| return result.action(value, result.operator);
|
| @@ -139,10 +125,8 @@ class ExpressionGroup {
|
|
|
| final List<Parser> _postfix = new List();
|
|
|
| - /**
|
| - * Adds a right-associative operator [parser]. Evaluates the optional [action] with
|
| - * the parsed `left` term, `operator`, and `right` term.
|
| - */
|
| + /// Adds a right-associative operator [parser]. Evaluates the optional [action] with
|
| + /// the parsed `left` term, `operator`, and `right` term.
|
| void right(Parser parser, [action(left, operator, right)]) {
|
| if (action == null) {
|
| action = (left, operator, right) => [left, operator, right];
|
| @@ -150,11 +134,11 @@ class ExpressionGroup {
|
| _right.add(parser.map((operator) => new _ExpressionResult(operator, action)));
|
| }
|
|
|
| - Parser _build_right(Parser inner) {
|
| + Parser _buildRight(Parser inner) {
|
| if (_right.isEmpty) {
|
| return inner;
|
| } else {
|
| - return inner.separatedBy(_build_choice(_right)).map((sequence) {
|
| + return inner.separatedBy(_buildChoice(_right)).map((sequence) {
|
| var result = sequence.last;
|
| for (var i = sequence.length - 2; i > 0; i -= 2) {
|
| result =
|
| @@ -167,10 +151,8 @@ class ExpressionGroup {
|
|
|
| final List<Parser> _right = new List();
|
|
|
| - /**
|
| - * Adds a left-associative operator [parser]. Evaluates the optional [action] with
|
| - * the parsed `left` term, `operator`, and `right` term.
|
| - */
|
| + /// Adds a left-associative operator [parser]. Evaluates the optional [action] with
|
| + /// the parsed `left` term, `operator`, and `right` term.
|
| void left(Parser parser, [action(left, operator, right)]) {
|
| if (action == null) {
|
| action = (left, operator, right) => [left, operator, right];
|
| @@ -178,11 +160,11 @@ class ExpressionGroup {
|
| _left.add(parser.map((operator) => new _ExpressionResult(operator, action)));
|
| }
|
|
|
| - Parser _build_left(Parser inner) {
|
| + Parser _buildLeft(Parser inner) {
|
| if (_left.isEmpty) {
|
| return inner;
|
| } else {
|
| - return inner.separatedBy(_build_choice(_left)).map((sequence) {
|
| + return inner.separatedBy(_buildChoice(_left)).map((sequence) {
|
| var result = sequence.first;
|
| for (var i = 1; i < sequence.length; i += 2) {
|
| result =
|
| @@ -196,7 +178,7 @@ class ExpressionGroup {
|
| final List<Parser> _left = new List();
|
|
|
| // helper to build an optimal choice parser
|
| - Parser _build_choice(List<Parser> parsers, [Parser otherwise]) {
|
| + Parser _buildChoice(List<Parser> parsers, [Parser otherwise]) {
|
| if (parsers.isEmpty) {
|
| return otherwise;
|
| } else if (parsers.length == 1) {
|
| @@ -208,7 +190,7 @@ class ExpressionGroup {
|
|
|
| // helper to build the group of parsers
|
| Parser _build(Parser inner) {
|
| - return _build_left(_build_right(_build_postfix(_build_prefix(_build_primitive(inner)))));
|
| + return _buildLeft(_buildRight(_buildPostfix(_buildPrefix(_buildPrimitive(inner)))));
|
| }
|
| }
|
|
|
|
|