p-hatan/ mirror

pub repository

mirror.p-hatan.com

petitparser

7.1.0

Build fast, composable, and type-safe grammars and parsers in Dart.

Cached in Iran · Upstream SHA-256 matched

Download archive

Readme

PetitParser for Dart

Pub Package Build Status Code Coverage GitHub Issues GitHub Forks GitHub Stars GitHub License

PetitParser makes writing parsers in Dart fast, enjoyable, and fully type-safe.

Instead of writing fragile regular expressions or configuring complex external code generators, PetitParser lets you build parsers directly in plain Dart code. You assemble small, specialized parsers like LEGO bricks to model everything from simple configuration values to full programming languages.

✨ Why PetitParser?

  • 🧩 Composable: Combine simple parsers into rich grammars using familiar operators and methods.
  • 🛡️ Type-Safe: Take advantage of modern Dart records, generics, and pattern matching without casting dynamic types.
  • ⚡ Fast & Efficient: Optimized character predicates and dedicated fast-path parsing keep execution blazing fast.
  • 🔍 Debuggable: Step through parsing in your IDE, inspect tokens, and visualize execution trees with built-in tools.
  • 🛠️ Extensible: Transform raw text directly into strongly typed models, syntax trees, or domain objects on the fly.
  • 🌐 Open Source & Battle-Tested: Highly tested, well-documented, and trusted across production Dart and Flutter applications.

🚀 Quick Start

Add PetitParser to your Dart or Flutter project:

dart pub add petitparser

Import the package, assemble your parser, and parse key-value pairs:

import 'package:petitparser/petitparser.dart';

void main() {
  // 1. Match a key of one or more letters:
  final key = letter().plus().flatten();

  // 2. Match a numeric value and convert it directly into an integer:
  final value = digit().plus().flatten().map(int.parse);

  // 3. Combine them: match key, discard '=', and match value:
  final entry = key.trim().skip(after: char('=')).then(value.trim());

  // 4. Transform the parsed pair into a typed Dart record:
  final parser = entry.map2((k, v) => (key: k, value: v));

  // 5. Parse the input:
  final result = parser.parse('port = 8080');

  print(result.value); // (key: port, value: 8080)
}

Notice what happened here:

  • letter().plus() matched consecutive letters, and .flatten() turned them into a String.
  • digit().plus() matched consecutive digits, and .map(int.parse) transformed them immediately into an int.
  • .skip(after: char('=')) consumed the separator without cluttering the result.
  • .then(...) combined both parts into a strongly typed record (String, int).
  • .map2(...) mapped both positional values into a readable named record.

🧩 Core Building Blocks

Every grammar in PetitParser is constructed from three fundamental concepts: matching text, combining parsers, and transforming results.

🔡 Matching Text

Primitive parsers recognize basic character patterns:

  • char('a') matches an exact single character:

    char('a').parse('a').value; // 'a'
    
  • string('dart') matches an entire string:

    string('dart').parse('dart').value; // 'dart'
    
  • digit() matches any digit from 0 to 9:

    digit().parse('7').value; // '7'
    
  • letter() matches any uppercase or lowercase letter:

    letter().parse('x').value; // 'x'
    
  • word() matches a letter, digit, or underscore:

    word().parse('_').value; // '_'
    
  • whitespace() matches spaces, tabs, and newlines:

    whitespace().parse(' ').value; // ' '
    
  • pattern('0-9a-fA-F') matches any character within a range:

    pattern('0-9a-fA-F').parse('f').value; // 'f'
    
  • any() matches any character:

    any().parse('!').value; // '!'
    

Most character parsers accept optional parameters such as ignoreCase: true for case-insensitive matching and unicode: true for full Unicode code-point support.

🔗 Combining Parsers

Snap individual parsers together to recognize structured input:

  • Sequences: Run parsers in order. letter().then(digit()) returns a typed Dart record with each result:

    letter().then(digit()).parse('a1').value; // ('a', '1')
    
  • Choices: Try options in order until one succeeds. [letter(), digit()].toChoiceParser() matches either a letter or a digit:

    [letter(), digit()].toChoiceParser().parse('a').value; // 'a'
    
  • Repetition: Repeat patterns to collect multiple matches into a List:

    • letter().star() matches zero or more times:

      letter().star().parse('abc').value; // ['a', 'b', 'c']
      
    • digit().plus() matches one or more times:

      digit().plus().parse('123').value; // ['1', '2', '3']
      
    • char('-').optional() matches zero or one time, returning null when absent:

      char('-').optional().parse('-').value; // '-'
      char('-').optional().parse('+').value; // null
      
    • letter().times(3) matches an exact number of occurrences:

      letter().times(3).parse('abc').value; // ['a', 'b', 'c']
      
    • digit().plusSeparated(char(',')) matches items separated by a delimiter:

      digit().plusSeparated(char(',')).parse('1,2,3').value.elements; // ['1', '2', '3']
      

🎨 Transforming Results

Rather than traversing an untyped syntax tree after the fact, PetitParser lets you transform data while parsing:

  • parser.flatten() merges matched characters into a single String:

    digit().plus().flatten().parse('123').value; // '123'
    
  • parser.trim() discards leading and trailing whitespace around a match:

    string('true').trim().parse('  true  ').value; // 'true'
    
  • parser.map(callback) transforms the parsed value with a custom function:

    digit().plus().flatten().map(int.parse).parse('42').value; // 42
    
  • parser.map2(callback) unpacks a two-element record and passes each value as an argument:

    letter().then(digit()).map2((l, d) => '$l:$d').parse('x9').value; // 'x:9'
    
  • parser.map3(callback) similarly unpacks a three-element record:

    (letter(), char(':'), digit())
        .toSequenceParser()
        .map3((l, sep, d) => '$l$sep$d')
        .parse('a:1')
        .value; // 'a:1'
    

🎯 Handling Results

Calling parse on a string returns a Result. You can inspect the outcome using Dart pattern matching:

final parser = digit().plus().flatten().map(int.parse);

void handleResult(Result<int> result) {
  switch (result) {
    case Success(value: final value):
      print('Parsed $value');
    case Failure(message: final message, position: final position):
      print('Error at $position: $message');
  }
}

handleResult(parser.parse('123')); // Parsed 123
handleResult(parser.parse('abc')); // Error at 0: digit expected

If you only need to know whether an input string conforms to your grammar, use accept:

if (parser.accept('123')) {
  print('Valid input');
}

To extract all matching occurrences across a larger body of text, use allMatches:

final words = letter().plus().flatten();
final matches = words.allMatches('two words 123');

print(matches); // (two, words)

🛠️ Practical Examples

📋 Delimited Lists

This example parses a comma-separated list of integers like '1, 2, 3' into a Dart List<int>:

final number = digit().plus().flatten().map(int.parse);
final numbers = number
    .plusSeparated(char(',').trim())
    .map((list) => list.elements);

final result = numbers.parse('1, 2, 3');
print(result.value); // [1, 2, 3]

list.elements gives you a typed List<int> containing only the parsed numbers, neatly dropping the comma characters.

🧮 Expression Builder

This example parses and evaluates mathematical expressions containing numbers, parentheses, negation, exponentiation, multiplication, division, addition, and subtraction:

import 'dart:math' as math;
import 'package:petitparser/petitparser.dart';

final builder = ExpressionBuilder<num>();

// Define primitives like floating-point or integer numbers:
builder.primitive(
  digit()
      .plus()
      .then(char('.').then(digit().plus()).optional())
      .flatten()
      .trim()
      .map(num.parse),
);

// Add parentheses with highest priority:
builder.group().wrapper(
  char('(').trim(),
  char(')').trim(),
  (left, value, right) => value,
);

// Add prefix operators:
builder.group().prefix(char('-').trim(), (op, value) => -value);

// Add right-associative power operator:
builder.group().right(
  char('^').trim(),
  (left, op, right) => math.pow(left, right),
);

// Add left-associative multiplication and division:
builder.group()
  ..left(char('*').trim(), (left, op, right) => left * right)
  ..left(char('/').trim(), (left, op, right) => left / right);

// Add left-associative addition and subtraction:
builder.group()
  ..left(char('+').trim(), (left, op, right) => left + right)
  ..left(char('-').trim(), (left, op, right) => left - right);

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

print(parser.parse('1 + 2 * 3').value);   // 7
print(parser.parse('(1 + 2) * 3').value); // 9
print(parser.parse('2 ^ 2 ^ 3').value);   // 256
print(parser.parse('-8 + 2').value);      // -6

🌲 Recursive Structures

This example parses nested JSON-style arrays of numbers like '[1, [2, 3], 4]' into a hierarchy of Dart lists:

final value = undefined<Object>();

// An array contains zero or more values separated by commas:
final array = char('[')
    .trim()
    .then(value.starSeparated(char(',').trim()))
    .then(char(']').trim())
    .map3((open, elements, close) => elements.elements);

final number = digit().plus().flatten().map(int.parse);

// Wire the recursive definition into the placeholder:
value.set([number, array].toChoiceParser());

final parser = value.end();

print(parser.parse('[1, [2, 3], 4]').value); // [1, [2, 3], 4]

🏛️ Large Grammars

When a grammar grows to dozens or hundreds of productions, organizing rules as separate variables can become difficult to maintain. Subclassing GrammarDefinition lets you organize rules as methods on a class, resolving complex mutual recursions cleanly.

This example parses and evaluates arithmetic expressions using a modular, strongly typed grammar definition:

class ExpressionGrammarDefinition extends GrammarDefinition<num> {
  @override
  Parser<num> start() => ref0(term).end();

  Parser<num> term() => [ref0(add), ref0(prod)].toChoiceParser();

  Parser<num> add() => ref0(prod)
      .then(char('+').trim())
      .then(ref0(term))
      .map3((left, _, right) => left + right);

  Parser<num> prod() => [ref0(mul), ref0(prim)].toChoiceParser();

  Parser<num> mul() => ref0(prim)
      .then(char('*').trim())
      .then(ref0(prod))
      .map3((left, _, right) => left * right);

  Parser<num> prim() => [ref0(parens), ref0(number)].toChoiceParser();

  Parser<num> parens() => char('(')
      .trim()
      .then(ref0(term))
      .then(char(')').trim())
      .map3((_, value, _) => value);

  Parser<num> number() => digit().plus().flatten().trim().map(num.parse);
}

References between rules use ref0(rule) to preserve strong types and resolve mutual dependencies dynamically when building the parser:

final definition = ExpressionGrammarDefinition();
final parser = definition.build();

print(parser.parse('1 + 2 * 3').value); // 7
print(parser.parse('(1 + 2) * 3').value); // 9

You can also build a parser starting from any specific production rule in the grammar using buildFrom:

final numberParser = definition.buildFrom(ref0(definition.number));
print(numberParser.parse('42').value); // 42

Organizing grammars this way makes them easy to navigate, refactor, and test production by production in your IDE.

🔬 Advanced Capabilities

📍 Source Positions and Tokens

If you are writing a compiler, linter, or syntax highlighter, you often need to know exactly where in the source file an element appeared. Wrap any parser with .token() to capture its start and stop offsets, line number, and column number:

final id = letter().plus().flatten().token();
final token = id.parse('hello').value;

print(token.value);  // 'hello'
print(token.start);  // 0
print(token.stop);   // 5
print(token.line);   // 1
print(token.column); // 1

🔭 Lookaheads and Semantic Guards

You can inspect the upcoming input stream without consuming characters:

  • parser.and() performs positive lookahead, succeeding only if parser matches next without advancing the input position.
  • parser.not() performs negative lookahead, succeeding only if parser fails to match next.
  • parser.where(predicate) rejects a match dynamically if a condition is not met.

For example, match a keyword like let only when it is not immediately followed by more word characters:

final keyword = string('let').skip(after: word().not());

print(keyword.parse('let').value); // 'let'
print(keyword.accept('letter'));   // false

⏳ Lazy Repetition

Standard repetition combinators like star() are possessive and consume as much input as possible. When matching delimited content like multi-line comments or quoted strings, use starLazy or plusLazy to stop as soon as a boundary parser succeeds:

final comment = string('/*')
    .then(any().starLazy(string('*/')).flatten())
    .then(string('*/'))
    .map3((start, body, end) => body);

print(comment.parse('/* note */').value); // ' note '

📏 Indentation-Based Grammars

Languages like Python or YAML use indentation rather than braces to define code blocks. The package:petitparser/indent.dart library provides Indent to coordinate indentation levels across nested structures:

  • indent.same: Matches and consumes the currently active indentation level.
  • indent.during(body): Increases indentation before running body, verifies deeper indentation, and restores the parent indentation level afterwards (with automatic rollback if body fails).

🩺 Grammar Linter

Grammars can contain subtle issues such as unreachable branches, infinite loops, or accidental left-recursions. PetitParser provides a built-in linter in package:petitparser/reflection.dart that you can run in your tests:

import 'package:petitparser/reflection.dart';
import 'package:test/test.dart';

test('grammar verification', () {
  final parser = letter().plus();
  expect(linter(parser), isEmpty);
});

⏱️ Debugging, Tracing, and Profiling

When a parser behaves unexpectedly on a particular input, wrap it with trace to see each step it takes:

final parser = letter().then(digit());
trace(parser).parse('a1');

This prints a clear activation tree showing which parsers were called and how they succeeded or failed:

SequenceParser2<String, String>
  SingleCharacterParser[letter expected]
  Success<String>[1:2]: a
  SingleCharacterParser[digit expected]
  Success<String>[1:3]: 1
Success<(String, String)>[1:3]: (a, 1)

For performance tuning, import package:petitparser/debug.dart and use profile(parser) to measure invocation counts and execution time per parser, or progress(parser) to inspect backtracking behavior.

📚 Resources

📜 History

Grammars for programming languages are traditionally specified statically. They are hard to compose and reuse due to ambiguities that inevitably arise. PetitParser combines ideas from scannerless parsing, parser combinators, parsing expression grammars (PEG), and packrat parsers to model grammars and parsers as objects that can be reconfigured dynamically.

PetitParser was originally created in Smalltalk. Later on, as a way to learn and explore these platforms, I reimplemented PetitParser in Java and Dart. All implementations share a consistent architecture while adopting the idioms and modern best practices of each target language.

📄 License

The MIT License, see LICENSE.

Changelog

Changelog

7.1.0

  • Dart 3.13 requirement.
  • Add .then to fluently construct strongly typed sequences.
  • Add specialized StringParser and StringIgnoreCaseParser.
  • Stabilize and optimize indentation-based parsing support (Indent parser): add Indent.during helper with automatic state rollback on failure, deprecate Indent.increase and Indent.decrease, and remove @experimental.
  • Optimize character predicate selection and lookup bit-testing.
  • Fix character range merging with contained sub-ranges (thanks to dylanpulver).
  • Fix character range optimization falsely returning ConstantCharPredicate.any.
  • Fix case-insensitive pattern parsing with inverted character ranges.
  • Expand and improve documentation and examples for sequence and choice parsers.
  • Rewrite and modernize README.md with approachable tutorials, typed Dart idioms, and practical examples.

7.0.2

  • Numerous fixes and improvements to documentation and examples.
  • Add a constant parser Parser.constant(Object value) that can be used to return a constant value.
  • Add a linter rule to detect duplicate parsers.

7.0.1

  • Dart and Flutter 3.9 compatibility.
  • Minor optimization to repeating character parsers.
  • Assertion on looping trim parser.

7.0.0

  • Dart 3.8 requirement.
  • Support for unicode character parsing in all relevant character parsers.
  • Most character parser constructors now uniformly support the following named arguments (breaking-change):
    • message: to customize the default error message;
    • ignoreCase: to accept lower- and upper-case variations; and
    • unicode: to decode surrogate pairs and instead of UTF-16 only.
  • For consistency and better flexibility in the future, replaced optional arguments to a named ones in various other constructors: Parser.flatten({String message}), Parser.not({String message}), Parser.neg({String message}), Parser.end({String message}), Parser.starString([String? message]), Parser.plusString({String? message}), Parser.timesString(int count, {String? message}), Parser.repeatString(int min, int max, {String? message}), failure({String message}), newline({String message}), undefined({String message}) (breaking-change).
  • Cleanup, simplifications, and optimizations to the codebase.
  • Removal of long deprecated code.

6.1.0

  • Improve documentation and fix broken links.
  • Prevent infinite recursion in repeating parsers.
  • Improve performance of case-insensitive string matching and the permutation parser.
  • Make the loopback variable in the expression builder public (thanks to joranmulderij).
  • Fix various bugs in equality testing of character predicates (thanks to North101).

6.0.0

  • Dart 3.0 requirement.
  • Use Dart Records for typed sequences:
    • Add convenience converter: (char('a'), char('b')).toSequenceParser()
    • And extension methods to emulate the old Sequence classes, deprecate old accessors.
  • Make Result a sealed class to be able to pattern match Success and Failure.
    • Removed the unused generic type of Failure, which is of type Result<Never> now.
    • Deprecated isSuccess and isFailure, instead use the more efficient is Success and is Failure operators.
  • Reintroduce hasSideEffect in MapParser and consider callbacks to be side-effect free by default.
  • The above changes give typical parser speed improvements between 10% and 30%.

5.4.0

  • Dart 2.19 requirement, enabled strict casts and type inference.
  • Introduce repeating character parser starString, plusString, timesString and repeatString for extra fast reading of strings.
  • Renamed AnyParser to AnyCharacterParser, and CharacterParser to SingleCharacterParser for consistency.
  • Add support for optional expression groups in the ExpressionBuilder.
  • Optimize, cleanup, and improve code and documentation.
  • Add optimize to in-place optimize parser graphs.

5.3.0

  • Maintenance release deprecating some old code in anticipation of the upcoming major release.
  • Deprecate the old way of defining primitive parsers and move the functionality directly to ExpressionBuilder.
  • Deprecate GrammarDefinition.build(Function, List<Object?>), use buildFrom(Parser) for a strongly typed parser instead.
  • Replace various uses of exception throwing with assertions, which yields code the compiler can optimize better.

5.2.0

  • Add @useResult to parser constructors to avoid bugs when using the old parser instance.
  • Add a linter rule to detect unoptimized flatten parsers.

5.1.0

  • Dart 2.18 requirement.
  • Add seq2, seq3, ... combinator functions returning strongly typed sequences of Sequence2<R1, R2>, Sequence3<R1, R2, R3>, ...
  • Add Parser.starSeparated, Parser.plusSeparated, Parser.timesSeparated, and Parser.repeatSeparated returning SeparatedList with the strongly typed elements and separators. Deprecate the dynamically typed Parser.separatedBy.
  • Add Parser.matchesAll that creates a lazy iterable over the (overlapping or non-overlapping) successful parse results. Deprecate matches and matchesSkipping.
  • Add a native platform independent newline parser.
  • Add a section on debugging to the tutorial.
  • Remove the deprecated ref0, ref1, ... instance methods, these methods are globally defined since 4.2.0.
  • Make GrammarDefinition and GrammarDefinition.start() optionally typed.

5.0.0

  • Dart 2.16 requirement.
  • Moved PetitParser examples to a separate Git repository: https://github.com/petitparser/dart-petitparser-examples.
  • Add a skip helper that silently consumes input before and/or after another parser.
  • Make the ExpressionBuilder<T> statically typed. This requires existing code to specify the desired result type, and provide all reduction actions.
  • Deprecate hasSideEffect in MapParser by considering all callbacks to have side-effects, the benefit of the added complications is negligible.
  • Add charIgnoringCase, and provide better standard error messages for character parsers.
  • Add initial support for indentation based grammars.

4.4.0

  • Dart 2.15 requirement.
  • Add a PatternParser that allows to use any Dart Pattern as a parser.
  • Greatly improve the test coverage of all code to 98%.

4.3.0

  • Dart 2.14 requirement.
  • Add a labeled parser, that allows to add a debug label to the parser graph.
  • Extract Predicate<T> and Callback<T> function types to shared file.
  • Change debug functions to named arguments, and generate output events with first class objects instead of strings.
  • Various improvements to the Analyzer:
    • Compute all deeply referenced children.
    • Compute all paths or the shortest path between parsers.
  • Fix inaccuracies in character parser documentation and tutorial.
  • Add more grammar linter rules that detect common bugs.

4.2.0

  • Dart 2.13 requirement.
  • ref0, ref1, ref2, ... is now also usable outside of GrammarDefinition.
    • Use resolve to inline all the referenced parsers, which now also works with SettableParser.
    • Deprecated removeSettables, that is superseded by the more powerful resolve operation.
  • Add the possibility to join multiple Token and transform their values.
  • Add Analyzer to compute nullability, as well as first-, follow-, and cycle-sets of parsers.
  • Add a linter that performs a series of checks on grammar graphs.
  • Expand the tutorial with a section on testing.

4.1.0

  • Add the option to select the failure join strategy on ChoiceParser parsers:
    • selectLast is the default strategy, reporting the failure of the last parser tried.
    • selectFarthest reports the parser failure the farthest down in the input string, preferring later failures to earlier ones.
    • selectFarthestJoined is the same as above, but joins error messages that happen at the same position.
  • Properly type all delegate parsers in choice, sequence, repeat, action, ...
    • Fix typing in transformParser and its users (debug tools, optimizers). To fix type your transformation function.
    • Fix typing of GrammarDefinition and reference parsers. To take advantage replace uses of ref with ref0, ref1, ...
    • Deprecate GrammarParser, a no longer needed wrapper around GrammarDefinition. Call build() on the definition to get the parser.
  • Improve documentation and add a tutorial section on GrammarDefinition.

4.0.0

  • Dart 2.12 requirement and null-safety.
  • Success.message throws an UnsupportedError exception, instead of returning null.
  • DelegateParser has been made abstract to avoid a concrete class in-between abstract classes.
  • Parser.delegate() has been removed, use Parser.settable() as an equivalent replacement.
  • Parser.optional() is now returning Parser<T?>, to provide a non-null default value use Parser.optionalWith(T value).
  • Parser.not() is now returning the failure Parser<Failure> as success value, instead of null.
  • epsilon() is now returning Parser<void>, to provide a non-null default value use epsilonWith(T value).
  • Removed const constructor from Parser hierarchy, as most parsers are inherently mutable and having some constant makes things inconsistent and more complicated than necessary.

3.1.0

  • Fix missing type information on eof and failure parser.
  • Optimize character predicates by using lookup tables.
  • Improvements to documentation and examples.

3.0.0

  • Dart 2.7 compatibility and requirement (extension methods).
  • New features:
    • String.toParser() enables creating efficient string and character parsers more easily.
    • Iterable.toChoiceParser() and Iterable.toSequenceParser() enables creating parsers from collections more easily.
    • Parser.callCC(Function) enables capturing a parse continuation more easily.
  • Restructure the internal code to be more modular:
    • The Parser class now only defines a few core methods, everything else is an extension method.
    • As long as you continue to import package:petitparser/petitparser.dart none of the changes should affect existing code.
    • Parser implementations have been moved to package:petitparser/parser.dart.
    • Helpers to parse and extract data has been moved to package:petitparser/matcher.dart.
    • The expression builder has been moved to package:petitparser/expression.dart.
    • The grammar builder has been moved topackage:petitparser/definition.dart.
  • Breaking changes:
    • Parser is no longer a Pattern, but can be converted to one with toPattern.
    • anyIn has been removed in favor of the already existing and equivalent anyOf parser.
    • pick and permute are defined on Parser<List>, thus they won't be available on the more generic Parser<dynamic> any longer. Prefix the operators with a castList operator.

2.5.0

  • Made ParserError a FormatException to follow typical Dart exception style.

2.4.0

  • Dart 2.4 compatibility and requirement.
  • More tight typing, more strict linter rules.
  • Documentation improvements.

2.3.0

  • Dart 2.3 compatibility and requirement.
  • The expression builder supports building expression with parenthesis.
  • Improved the documentation on greedy and lazy parsers.
  • Add a prolog parser and interpreter example.
  • Numerous optimizations and improvements.

2.2.0

  • Dart 2.2 compatibility and requirement.
  • Parser implements the Pattern interface.
  • Add an example of the expression builder to the tutorial.
  • Introduce a fast-parse mode that avoids unnecessary memory allocations during parsing.

2.1.0

  • Rename ParserError to ParserException, and make it an Exception.
  • Simplify the EndOfInputParser and the ListParser.
  • Add a PositionParser that produces the current input position.
  • Constructor assertions across the stack.

2.0.0

  • Make parsers fully typed, where it makes sense.
    • In most cases this should have no effect on existing code, but sometimes can point out actual bugs.
    • In rare cases, it might be necessary to insert cast<R> or castList<R> at the appropriate places.
  • Move examples into their own example package.

1.8.0

  • Drop Dart 1.0 compatibility.

1.7.6

  • More Dart 2 strong mode fixes.

1.7.5

  • Dart 2.0 strong mode compatibility.
  • Removed deprecated code, and empty beta package.
  • Reformatted all code using dartfmt.

1.7.0

  • Dart 2.0 compatibility.
  • Fixed numerous analyzer warnings.
  • Generate better default error messages.
  • Moved example grammars to examples.

1.6.1

  • Fix bug with duplicated package name.
  • Update documentation.

1.6.0

  • Migrate to micro libraries.
  • Move Smalltalk, Json, Dart and Lisp grammars to examples.

1.5.5

  • Strict typing fixes.

1.5.4

  • Fix analyzer warnings.
  • Fix package dependencies.

1.5.3

  • Dev compiler support.

1.5.2

  • Enable strong mode.

1.5.1

  • Improve the Dart parser and add more tests.

1.5.0

  • Update documentation to match the style guide.
  • Change library names.
  • Add optimizations and tests for the Dart language grammar.
  • Improve comments.
  • Better error-handling and primitives for Lisp command line app.
  • Fix unicode parsing in the JSON parser.
  • Add browser back to dev_dependencies.

1.4.3

  • Restore the CompositeParser class.
  • Add more references to open source projects using PetitParser.

1.4.2

  • Integrate the tutorial into the README.
  • Improve formatting of README code blocks.

1.4.1

  • Improve test coverage.
  • Bump minimum SDK to 1.8.0.
  • Remove deprecated CompositeParser class.

1.4.0

  • Migrate from unittest to test.
  • Setup Travis.
  • Allow for const GrammarDefinitions.
  • Fix typo in docs.
  • Clean up the JSON grammar.
  • Format the benchmarks.

1.3.7

  • Cleanup dependencies:
    • browser is now >=0.10.0 <0.11.0.
    • unittest is now >=0.11.0 <0.12.0.
    • Remove explicit dependency on matcher package.
  • Make the JSON parser twice as fast.
  • Reformat tests.

1.3.6

  • Add a benchmark for JSON native vs PetitParser.

1.3.5

  • Change hasEqualProperties to gracefully handle parsers of inconsistent types.

1.3.4

  • Format source code.
  • Add missing documentation.

1.3.3

  • Performance optimizations

Installing

export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add petitparser
pubspec.yaml
name: petitparser
version: 7.1.0

homepage: https://petitparser.github.io
repository: https://github.com/petitparser/dart-petitparser
description: Build fast, composable, and type-safe grammars and parsers in Dart.
screenshots:
  - description: 'PetitParser'
    path: petitparser.png
topics:
  - grammar
  - parser
  - parser-combinator
  - parsing
  - peg

environment:
  sdk: ^3.13.0
dependencies:
  meta: ^1.19.0
  collection: ^1.19.1
dev_dependencies:
  lints: ^6.1.0
  test: ^1.31.2

Version history

VersionPublishedArchiveSHA-256
0.1.02012-10-23T18:16:56.176760ZCachedf54c4ff1366ffdc5b4bf9786b6d809aca48118a1a51f813ba0aaf146507d1f0f
0.2.02012-12-18T17:13:46.500870ZCacheda6f3d4f81c07aaf77bc4e6c271e8cd16d1de24920234b7104a0bd4598f0a2fcb
0.2.12013-01-17T19:12:51.736850ZCached560e323ca680bb215dcb354821cb1020dfa35a07118e368cf53095227b11782c
0.2.2+m32013-01-23T19:20:57.023750ZCachedf7a5556334db97017a64231fd2797e07035f494bae0b65ac79de14e1705ae7d4
0.2.3+m32013-03-04T07:47:59.328190ZCached3c555c58a64405abaf402b5ce2620e91f5b06420a4be2c1cc2baf0cfa5df765a
0.2.4+m42013-03-20T04:02:03.085030ZCachedd3c7d873f43d35990598d7d2694fa9d8d0fe466c12b055bc0c03881ad77502bf
0.2.5+m42013-04-11T18:45:58.734330ZCached6b2d59b917f4e6fc5d1ac9667fb983917056fd10e913f6e0bbd157817c6a92d9
0.3.02013-04-17T18:57:29.265130ZCached57ebc797dfe3686f97dbe0afe6bbf38281120ad0088dfbb683d99a5218d0e398
0.4.02013-04-29T22:09:19.837990ZCached912ce5f47d56893cca55fb0dc9ffb32094c652f04929bf5d21c3dd16dadb3d1e
0.4.12013-05-02T20:23:06.978340ZCachedb05875e99ae10481bbd1499d7cebf3aa60f634cf23dd8c61fc13f36cab40b77b
0.4.22013-05-20T10:06:25.835800ZCached9781136a9c8f200d1408fd569dbd172776891a6027f1bdec92bda7345a2b9e27
0.4.32013-05-30T19:05:27.659710ZCached6ffea950edf9e56f102b35283343aee730aa456d483dd425f0b005538462ec4e
0.5.02013-07-03T20:34:16.666390ZCached5fe185f5956a814dc7f43edce6f8161246d06f6e93200b207d66c056e9911ddc
0.5.12013-08-02T22:02:52.142070ZCached60787a806b5572af688194b287cc2a6049a17417c351bebc034e815db6f3003b
0.5.22013-08-15T08:27:56.517430ZCacheda8eb809ce0295b395432e51f13a003a777e88e369f412bf662cf6a787096f7e0
0.5.32013-09-09T15:07:36.207320ZCached58faced45be6614412dae2a43df5067ddb06455a8fcbf6eef9ec6a9051226127
0.5.42013-09-17T11:49:05.269910ZCachedf082cafefc15f0a9cbef5d9fc2194160f2c6c0a35385454192394ff6b721c731
0.5.52013-10-05T09:55:28.974950ZCachedff7e2e742af0ee2f64293dc8324a0bc7a185ff550fa52fa7f02ab3c46204841c
0.5.62013-10-29T07:19:20.308840ZCached2dda7e9b3b84644a4e0f59bbf4c0147fed48696660ae5fe28ae2091a0e5d96c7
0.5.72013-11-07T18:18:43.058070ZCached24d14d94697a5374cd072c392e284cac58223d98b06d5c369d0413a1e20daf0e
1.0.02013-11-08T21:19:16.954210ZCachedb3728c601c3aa31e2571f4a801ac73f0a0a603f95c074f49aee34a477862ca01
1.0.12014-01-07T17:04:30.124690ZCachededa0d023bb7c07a0c578d2cb2b4ccb218dfbf74a30da83dadba855e00898527d
1.1.02014-02-09T21:31:14.770470ZCached8a3b7d51f3c0b4ee61600058a0bfca5643ed186fb60e1e60927b114d51d855c1
1.1.12014-02-28T07:36:55.844440ZCachedf637a759a3adabcefac48d632f902a528d6eeaa264943ce74ff23e1cc5d98b04
1.1.22014-04-21T18:03:59.118710ZCached9f87252b392806ff20b5514b43dc041cfb6e05c326d1082c119a3c754b4f43de
1.1.32014-05-17T17:53:13.184250ZCached6c4a24f45ad4e2c85cc2b813946c3daa92f458d7419bdb9359a59cad39d4cea4
1.2.02014-07-06T14:47:20.271230ZCacheda4add18fa4709a3cf1ba26de158bf18eef598b54a2a85de5047f4883f50386a0
1.2.12014-08-01T17:32:20.171550ZCachedeff26935e49ed1bd2cb80c7a800d0d9006b8a44d00a75c46df52949ef0c813ff
1.2.22014-08-16T10:27:32.560340ZCachede312bc7b1925154f9532b56420460a28bbfd8065df9722d22a8eb38251811e5d
1.3.02014-11-15T14:01:56.751460ZCached1fb3cbd841cac9d42d2a639e228d6b329270cee1050c52ade752656fea58fe55
1.3.12014-11-29T08:13:28.023970ZCached2885cb5892fb538d4d991bc9fb3293a371b9cf36778c3b7eb72eabdf0c155d0c
1.3.22014-12-14T11:01:49.298150ZCached2aba483ab5b87dc68c1f1e9c265ca9bae5a267c69efea95ec180d4ad9f14a190
1.3.32014-12-27T17:57:12.368800ZCached7c6ba4652bd9ecdb3e6893dea48de98456329838c3ac17990eabf4c7393f5f42
1.3.42015-01-23T21:00:41.840690ZCached3d9b4f60f8c4aa745cc6114ec23711137c69fbdf24b49f41c123b5890266a3a8
1.3.62015-02-11T08:49:12.415680ZCachedce4e39f601b64b02adfe07b95eb409a2439a12a3d2f7a348a9993c8b75adeb32
1.3.72015-02-27T18:39:53.288380ZCachedc0aab2cd35c85877b623bb6a0d5556a482680874ab77bf2c2c403fc5ca2c8749
1.4.02015-05-15T11:51:10.014ZCached2f8eb930944f1e9138077cf38f9d82f024c57efdcdf8950a6b7e7eaefe0da08d
1.4.12015-05-15T16:06:56.876ZCached5414728596a07e38592ab87b1a19643cdbdbf5ce580747c291d33e680b4e1780
1.4.22015-05-17T09:44:54.966ZCached6fc9effe307f31c6ad2fb465ace78eaddeaa8cff3becde5101befb4d9c3ec17b
1.4.32015-05-17T15:37:38.002ZCached49af578832195bba5d2e48ff58a8b89c8504e42c7c5f35c67bfb404752ac4c4f
1.5.02015-10-06T18:08:39.912ZCached763239e6b0009e9276a90d11c0a179c871967f87cbfe694d0b673a8ab540a4e5
1.5.12016-01-17T10:08:08.791ZCached620dbddfcc3b83fc327e0249e33eb5ba4c91c178775bdfb0b88e6424294e3746
1.5.22016-04-05T10:22:08.428ZCached99a1ec032d9b3d5cd73a8f36d5c1d64a0d213bbada1b093d4d04698adbc08c5b
1.5.32016-04-05T10:34:18.270ZCachedf20cbc743ce54b11127e74653edf8efebbe5929e340f4ab1142d81c662d6b090
1.5.42016-10-17T15:25:21.622ZCached63a945886e32d1b32e6c4f58221b428591b5795da4c39f0ac40de461ab25f9b0
1.5.52017-07-04T11:17:05.473346ZCached32ce3727e2eb402c82e5f6638b75f50dbfc94f8ed999e1606c779a0c25b10ada
1.6.02017-08-04T20:09:18.176831ZCachedeb050332bda8182b0cb9a5dd2d6804be3ee6c136cd180faf5f26e3c36cd10f74
1.6.12017-08-31T21:30:05.922015ZCachedccc2ef030855d102a0f8c02e1889eec6507359a7d879f39fba63041932c76f1b
1.7.02017-12-19T19:55:11.595620ZCachedf1c072036ca2ee6bb19b363febfd7076bd38f61430bac8359fd4ac50b11b15c5
1.7.12018-03-08T19:08:27.354961ZCachedbc50c1eba95cc564cebee90c793436eba637e45995106355423282bcf2ad45e2
1.7.22018-03-08T19:34:22.645002ZCachedf22f3ffdef00a793a3b38e96a41a399384c09da8e8df34bd7ee2c9d41fb1abb9
1.7.32018-03-08T19:37:35.602492ZCachedbe43ac2a3c2dfe79dfeceeff9e9eb3f467876e2767f7ac554d34a959237b7397
1.7.42018-03-09T12:32:00.941207ZCachedacdbaba7ce6b2f4ef95479ea98c5fd1a76d198f5588f3da6814af3f4c31eb936
1.7.52018-03-09T22:24:56.411460ZCached6fc8914c448dfe59594f6dcefda65bae29caa6420b9f9929f13f1edcf7bd4191
1.7.62018-03-15T08:43:01.044334ZCachedad187be44d18a5965f8cc129af6e360ce8e3cc11f81b93085dbde0e7cca38571
1.7.72018-07-21T14:08:33.941326ZCached1884c28ad0060c2b0a3b9ddef5a6986c07494d62786c670816d174bbc0f87575
2.0.02018-08-01T18:47:52.414261ZCached2b5c9e2f1cb33441b156ceeedfa82d1b3e892510f03b78278c1cc88a4df1f343
2.0.12018-09-15T19:29:06.877263ZCached034cc842fff1ee473f8124da502414282896e3471c52322464e9b213d5c81ad5
2.0.22018-09-27T14:09:05.849616ZCached528516f16e35b0aed538b145feb79e1f610165c9ab10c5508e499c88689071a7
2.1.02019-01-07T21:27:38.118964ZCached059ae18865269fdf10d25afe5a2d3379efa710fd23d471fa52fca4439511d23c
2.1.12019-01-24T14:39:52.212011ZCached108c94d0766fb1afa42228af753f53d085d9bdd6dc3aef607ca5c58f4d6496a5
2.2.02019-02-27T20:29:54.952683ZCached2ccfcf4be74d4427a47b1df466d7ac3027797680068a0e86a4f7633d2a569c3a
2.2.12019-03-07T06:19:05.828783ZCached1f4f9ab4bbb08398b8e4bb0943016283d9b08a5f738661d588b2ec8b3010cbdf
2.3.02019-05-10T13:32:28.094817ZCached80c100878a233febeb8678825c8d0ad513fe349889897a9cf89334d37236cc7e
2.4.02019-06-28T20:15:28.073171ZCached4525e4341c9aabc4023700abff9b2e26f969dff9476ddf8f40de63ee5748acab
3.0.02020-01-01T09:59:43.151919ZCached382799fb2c795cd0eac17db2a4a88df01c098a248ca4e6ae456f52019b5f9cb1
3.0.12020-02-12T10:46:56.868354ZCacheda6adb2f6edd16883b5bd36c667b0cf895cb3553fe2e274dc277b6cdedeaace98
3.0.22020-03-30T17:33:45.672316ZCached5d409b6c77f0fcf944034a1d2a13afbc3297bd34f05771aed2193bf15814c039
3.0.32020-05-30T07:27:08.796109ZCached3817f3d6d36048c60b1a5d0f48866d0f428d031616caeb16705e21e6f6682239
3.0.42020-05-30T10:07:04.173553ZCached6802205ca621e6d2d2fc315d89491a685c33a16bf82875327aab0295afb3ec4f
3.1.02020-07-18T09:25:27.838333ZCachedfe07f9345bf03ff0c881d1f5494e20cc40206780ca5dea86aab8037cb49af5f2
4.0.0-nullsafety2020-09-07T16:56:25.699722ZCached641666f59c207a4104d3deec59db627d4368aa3415ccb9982ecc7dc6802d7d57
4.0.0-nullsafety.12020-11-21T07:57:07.968835ZCached12576308c0232b8a2acc6b66710c4920ed760f4466f5dee63ff7c6782633019b
4.0.02021-02-17T21:44:05.867149ZCached3aac98525056d0ae4b397245d9523e51f3326b8fcd83d14bdd186435c6ec4b77
4.0.12021-02-19T10:50:55.719144ZCached88917a76a71fc578cfdbeb44b4da718c4c4e098de6a41153c200825195b80e53
4.0.22021-02-19T13:22:00.265489ZCachedf725a68581f744b9cdc680e525a20fb86491053bf5ee23562e0d6ea3ee1c173c
4.1.02021-04-05T15:37:16.055645ZCached85e8f8b118afcccf948a9844d199e56260117400bd9b9982d87bf1d62ebc1690
4.2.02021-06-05T14:12:12.269755ZCached3abc4a0f06dccb2348ebdab9f5b9cc88bb64bfc830bed6351040ca42722044a6
4.3.02021-09-10T18:32:53.045212ZCachedb1e35bcd00e0ab63a4883d7d76461da7477dcac3ab82fa0ab894be729d579032
4.4.02021-10-16T08:24:26.114183ZCached1a914995d4ef10c94ff183528c120d35ed43b5eaa8713fc6766a9be4570782e2
5.0.02022-03-11T14:55:52.026405ZCached2ebb289dc4764ec397f5cd3ca9881c6d17196130a7d646ed022a0dd9c2e25a71
5.1.02022-10-23T15:14:59.189671ZCached49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4
5.2.02023-02-19T11:25:06.902830ZCached32e46db8021f6d027d9221b937653f5c8aa043e0dc093998e18331912f22936b
5.3.02023-03-05T13:16:58.372115ZCacheda9346a3fbba7546a28374bdbcd7f54ea48bb47772bf3a7ab4bfaadc40bc8b8c6
5.4.02023-04-24T11:27:43.900104ZCachedcb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
6.0.02023-08-17T19:22:40.433530ZCached54e61005585962c9cb6f0df05a3ed82453e01deb1b1f83833b0b6cf7eab93da4
6.0.12023-08-20T10:07:28.358866ZCachedeeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6
6.0.22023-11-30T10:30:42.598779ZCachedc15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
6.1.02025-01-12T10:15:53.275595ZCached07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646
7.0.02025-06-15T14:26:01.701287ZCached9436fe11f82d7cc1642a8671e5aa4149ffa9ae9116e6cf6dd665fc0653e3825c
7.0.12025-08-16T09:33:44.998191ZCached1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1
7.0.22026-02-14T10:03:01.017261ZCached91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675
7.1.02026-09-27T06:29:16.945839ZCached2f1564aadb14215e478563b5406cb80729d022158c01dc50c96013c2f7eb4790

Dependencies

collection "^1.19.1"

meta "^1.19.0"