flutterdartpetitparser

Dart PetitParser to get at AST datastructure created with ExpressionBuilder


I'm new to petitparser, but it looks like it's the sonic screwdriver of parsers.

For my first project, I'm building code to parse a simple expression that builds an AST tree of my Node objects, then walks that tree with a few rules to minimize the unneeded parens. I don't know what to pass to the output of .parse() (seems to be a Result) to get access to the tree I defined, so I can call .visit() on the top of the AST. Any ideas?

class RIPParser {
  Parser _make_parser() {
    final builder = ExpressionBuilder();

    // precedence 5
    builder.group()
      ..primitive(digit()
          .plus()
          .seq(char('.').seq(digit().plus()).optional())
          .flatten()
          .trim()
          .map((a) => Node(precedence: 5, value: a)))
      ..wrapper(char('(').trim(), char(')').trim(),
          (l, a, r) => Node(precedence: 5, left: l, value: a, right: r));
    // negation is a prefix operator
    // precedence 4
    builder.group()
      ..prefix(
          char('-').trim(), (op, a) => Node(precedence: 4, value: '$op$a'));

    // power is right-associative
    // precedence 3
    builder.group()
      ..right(char('^').trim(),
          (a, op, b) => Node(precedence: 3, left: a, value: op, right: b));

    // multiplication and addition are left-associative
    // precedence 2
    builder.group()
      ..left(char('*').trim(),
          (a, op, b) => Node(precedence: 2, left: a, value: op, right: b))
      ..left(char('/').trim(),
          (a, op, b) => Node(precedence: 2, left: a, value: op, right: b));
    // precedence 1
    builder.group()
      ..left(char('+').trim(),
          (a, op, b) => Node(precedence: 1, left: a, value: op, right: b))
      ..left(char('-').trim(),
          (a, op, b) => Node(precedence: 1, value: op, left: a, right: b));

    final parser = builder.build().end();

    return parser;
  }

  Result parse(String input) {
    var parser = _make_parser();
    var result = parser.parse(input);
    return result;
  }

Solution

  • In short call result.value to get your parse-tree, or to throw a ParserException in case of an error.

    For more details have a look at the class documentation of Result, which is either a Success or a Failure instance. In both cases the objects contain extra information, such as how much input was consumed or in case of an error what went wrong.

    Update: I've tried to clarify the documentation on the mentioned classes in 8698f91.