Simple Java Example

dvberkel edited this page Sep 25, 2014 · 6 revisions
Clone this wiki locally

To give you a feel for what grammar specification looks like with parboiled for Java consider the following classic “calculator” example, with these rules in a simple pseudo notation:

Expression ← Term ((‘+’ / ‘-’) Term)*
Term ← Factor ((‘*’ / ‘/’) Factor)*
Factor ← Number / ‘(’ Expression ‘)’
Number ← [0-9]+

A parboiled parser definition, complete and in ready-to-compile Java code would look like this:

@BuildParseTree 
class CalculatorParser extends BaseParser<Object> {

    Rule Expression() {
        return Sequence(
            Term(),
            ZeroOrMore(AnyOf("+-"), Term())
        );
    }

    Rule Term() {
        return Sequence(
            Factor(),
            ZeroOrMore(AnyOf("*/"), Factor())
        );
    }

    Rule Factor() {
        return FirstOf(
            Number(),
            Sequence('(', Expression(), ')')
        );
    }

    Rule Number() {
        return OneOrMore(CharRange('0', '9'));
    }
}

As you can see, the rule description from above translates directly into readable Java code (which is formatted here for readability, not minimization of line count). The class defines the parser rules (yet without any actions), which can be used to parse actual input like this:

(1) String input = "1+2";
(2) CalculatorParser parser = Parboiled.createParser(CalculatorParser.class);
(3) ParsingResult<?> result = new ReportingParseRunner(parser.Expression()).run(input);
(4) String parseTreePrintOut = ParseTreeUtils.printNodeTree(result);
(5) System.out.println(parseTreePrintOut);

Line 2 creates a parser instance whose rule creating methods can then be used with the various ParseRunners to perform an actual parsing run and create a ParsingResult object (line 3). Apart from the information whether the input was successfully matched the ParsingResult object contains the root of the parse tree for the expression (if parse tree building is enabled), the result value (which is null in this parser without actions) and a list of parse errors. A quick way for understanding how your parser digested the input is to print the created parse tree with ParseTreeUtils.printNodeTree as shown in line 4 and 5.

In general parboiled was designed to make your rule specification as clean and readable as possible under the constraints of the Java syntax. For more examples (including actions, AST construction, etc.) please see the Java Examples.