peg2 0.1.34

  • Readme
  • Changelog
  • Example
  • Installing
  • 50

peg2 #

Development was discontinued due to a lack of interest from users. #

PEG+ (Parsing expression grammar) parser source code generator, command line tool.

Version 0.1.34

This is a slightly modified (extended) version of PEG with support for nonterminal, terminal and subterminal symbols and with the support of the expression "Capture".

Warning #

This software does not contain public API because it is a tool (utility).

Planned features #

All planned improvements and discovered flaws can be found in the "todo.txt" file.

Activation and usage #

Since this software is a command line utility, it requires activation.
To activate, you must run the command:

pub global activate peg2

After activation, the utility is ready for use.

Example of use:

pub global run peg2 json.peg

Remember to periodically update this software to get the latest version.

Grammar #

Grammar consists of production rules.
Rules are of three types: nonterminal, terminal and subterminal.
For each type of rule, a naming convention is defined.

Below are examples of rule naming:

  • Nonterminals: Value, value, someValue2
  • Terminals: 'string', 'end of file', '['
  • Subterminals: @spacing, @SPACING, @Identifier

Production rules #

Each rule is an ordered choice and consists of a single ordered choice expression (OrderedChoice), which consists of parsing variants.
Each parsing variant is a sequence (Sequence) of parsing expressions, each of which, in turn, may consist of other parsing variant expressions (OrderedChoice).

Production rules return values. Return types can be specified explicitly or they can be inferred from return types of expressions OrderedChoice.
Return types of OrderedChoice expressions, in some cases, can be inferred from return types of Sequence expressions.
Return types of Sequence expressions can be inferred from the types of returned results of the expressions involved in the formation of the result.

In the case when a semantic action is used to generate the result, the type of the return value cannot be inferred automatically. In this case, it is recommended to specify the type of the returned result explicitly.

Example of explicitly specifying the type of the return result:

bool 'false' =
  "false" @spacing { $$ = false; }

Sequence expression #

Each expression generates a result, but the main result is formed by the expression Sequence.
The expression Sequence allows you to use semantic actions to forming results.
In semantic action semantic values (variables) can be used.

An example of using semantic variables:

List<MapEntry<String, dynamic>> Members =
  m:Member n:(',' m:Member)* { $$ = [m, ...n]; }
  ;

MapEntry<String, dynamic> Member =
  k:'string' ':' v:Value { $$ = MapEntry(k, v); }
  ;

Principles for forming the results of a sequence of expressions #

Case #1:
No semantic variables. No semantic action.
In this case, the return result will be the result of the first expression (@IDENTIFIER).

'type name' =
  @IDENTIFIER @SPACING
  ;

Case #2:
One semantic variable. No semantic action.
In this case, the returned result will be the result of the expression stored in the variable (v).

Json =
  'leading spaces'? v:Value 'end of file'
  ;

Case #3:
Several semantic variables. No semantic action.
In this case, the returned result will be a list of the results of all expressions stored in all variables ([k, v]).

KeyAndValue =
  k:'string' ':' v:Value
  ;

Case #4:
Semantic action specified.
In this case, the returned result must be formed in semantic action and assigned to the special variable "$$".
Semantic variables will be available for use to forming the result.

String 'string' =
  "\"" c:@char* "\"" @spacing { $$ = String.fromCharCodes(c); }
  ;

Capture expression #

The expression Capture allows you to capture parsed text from the beginning to the end of the expression Capture, without having to form the result from the results of child expressions.
The syntax for this expression is <e>, where e is any expression, including a sequence of expressions (Sequence).
This is convenient enough for obtaining a parsing result that corresponds to the parsed text and does not require transformations. You just capture the text and that’s all you need to do in this case.

Examples:

'library prefix' =
  <[_]? @IDENTIFIER>
  ;
'globals' =
  "%{" b:<@GLOBALS_BODY*> "}%" @SPACING
  ;

Terminal expressions #

Terminal expressions respond directly to parsing the text.
The following expressions are terminal expressions: AnyCharacter, CharacterClass and Literal.
They can consume any character, a character from a specified range, or text, respectively.
Terminal expressions cannot be used directly in nonterminal rules.

A little more words about production rules #

Nonterminal rules

Nonterminal parsing rules are the high level of parsing.
They can consist of nonterminal and terminal rules, combined by any expressions.
Nonterminal parsing rules cannot contain terminal expressions such as AnyCharacter, CharacterClass and Literal.

Terminal rules

Terminal rules, in turn, are the low level of parsing. They can consist of subtermial rules and terminal expressions such as AnyCharacter, CharacterClass and Literal.

Subterminal rules

Subterminal rules are a sublevel of the low level, which is essentially intended to simplify the writing of grammar, by transferring the most commonly used low-level parsing procedures to the subterminal rules. They can consist of subterminal rules and terminal expressions.

To be continued...

0.1.34 #

  • Development was discontinued due to a lack of interest from users

0.1.33 #

  • Reworked ExpressionToEnfaConverter
  • Fixed bugs in ExpressionToEnfaConverter
  • Fixed bugs in EnfaToNfaConverter
  • Fixed bugs in NfaToDfaConverter

0.1.32 #

  • Minor corrections in the implementation of the propagation of the flag productiveness and in using this flag

0.1.31 #

  • Fixed bugs in productiveness analysis of expressions

0.1.30 #

  • Fixed a bug in prediction mode, added error handling in case of predicting rule call bypass

0.1.29 #

  • Improved performance of the generated parser with the enabled prediction mode (--predict)
  • Minor changes (corrections) in some algorithms of analyzers and generators
  • Fixed incorrect usage (bug) of ActionGenerator

0.1.28 #

  • Added a new (experimental) feature finite automaton, for better grammar analysis
  • Improved the analysis and search (using a finite automaton) for symbol expressions and production rules that may be involved in the process of memoization
  • Changed (simplified) the memoization algorithm in generated parser, excluded the procedure for dynamic determination of the need for memoization of rules

0.1.27 #

  • Removed unnecessary leading zeros from the local variable generator
  • Minor fixes in the memoization algorithm

0.1.26 #

  • The algorithm for generating the expression Sequence has been improved

0.1.25 #

  • Added command line option --optimize-size

0.1.24 #

  • Minor changes in the behavior of the predicate expression to improve error reporting

0.1.23 #

  • Fixed bugs in ExpressionStartCharactersResolver

0.1.22 #

  • Fixed bugs in ExpressionStartCharactersResolver
  • Redesigned class hierarchy
  • Added new optimization method: final variables usage optimizer

0.1.21 #

  • Redesigned the architecture and structure of generators
  • Reworked the production rule methods generator, improved reuse of initial variables in expressions
  • Minor improvements of code generators, now generated code is even cleaner ans shorter
  • Small changes in the algorithm of the generated expressions
  • Fixed bugs in VariableUsageOptimizer
  • Improved UnusedVariablesRemover
  • Fixed bugs in GeneralProductionRulesGenerator.visitSequence()

0.1.20 #

  • Fixed bugs in analyzer InvocationsResolver, the analyzer has been reworked

0.1.19 #

  • Minor changes (corrections) to the grammar file peg2.peg

0.1.18 #

  • Removed (as unnecessary) analyzer directive ignore_for_file: unused_local_variable from generated code
  • Removed (as unnecessary) analyzer directive ignore_for_file: prefer_final_locals from generated code
  • Reworked and improved error handling system, it has become simpler, clearer, more reliable and a little faster

0.1.17 #

  • Improved (changed) algorithm for generating expressions SequenceExpression and OrderedChoiceExpression, reduced amount of generated code

0.1.16 #

  • Added command line option --optimize-code
  • Improved failure reporting
  • Added new optimizer: VariableUsageOptimizer
  • Improved optimizer: UnusedVariablesRemover
  • Improved optimizer: ConditionalOperationOptimizer, added functionality to remove empty statement blocks

0.1.15 #

  • Fixed bug in generator AnyCharcterExprtession with the Unicode character greater then 0xffff

0.1.14 #

  • Fixed bug with an increment value of _pos_, the length of the Unicode character was not taken into account

0.1.12 #

  • Implemented experimental prediction feature, command line option --predict
  • Added feature: convert terminal calls into inline expressions, command line option --inline-terminals
  • Added feature: convert all calls into inline expressions, command line option --inline-all

0.1.11 #

  • Added new resolver: ExpressionProductivenessResolver
  • Improved performance of the match expressions
  • Improved failure tracking performance

0.1.10 #

  • Memoization algorithm made more optimal

0.1.9 #

  • Improved performance of experimental memoization feature

0.1.8 #

  • Implemented experimental memoization feature, command line option --memoize

0.1.7 #

  • Implemented conditional operation optimizer to transform conditional operations

0.1.6 #

  • Removed import of dart:html. How was it added?

0.1.5 #

  • Added feature: convert nonterminal calls into inline expressions, command line option --inline-nonterminals
  • Added feature: convert subterminal calls into inline expressions, command line option --inline-subterminals

0.1.4 #

  • Added (experimental) support of NNBD type naming convetion to grammar peg2.peg
  • Added support of library prefix to grammar peg2.peg

0.1.3 #

  • Added a small description and instructions for use

0.1.2 #

  • Fixed source code according to pub.dev health suggestions

0.1.1 #

  • Fixed source code according to pub.dev health suggestions

0.1.0 #

  • Initial release

example/example.dart

// Generated by 'peg2'
// https://pub.dev/packages/peg2

void main() {
  final parser = ExampleParser();
  final result = parser.parse(_text);
  if (parser.error != null) {
    throw parser.error;
  }

  print(result);
}

final _text = '''
{"rocket": "🚀 flies to the stars"}
''';

class ExampleParser {
  static const _eof = 0x110000;

  FormatException error;

  int _c;

  int _error;

  List<String> _expected;

  int _failure;

  List<int> _input;

  List<List<_Memo>> _memos;

  var _mresult;

  int _pos;

  bool _predicate;

  dynamic _result;

  bool _success;

  String _text;

  dynamic parse(String text) {
    if (text == null) {
      throw ArgumentError.notNull('text');
    }
    _text = text;
    _input = _toRunes(text);
    _reset();
    final result = _parseJson(false, true);
    _buildError();
    _expected = null;
    _input = null;
    return result;
  }

  void _buildError() {
    if (_success) {
      error = null;
      return;
    }

    String escape(int c) {
      switch (c) {
        case 10:
          return r'\n';
        case 13:
          return r'\r';
        case 09:
          return r'\t';
        case _eof:
          return 'end of file';
      }
      return String.fromCharCode(c);
    }

    String getc(int position) {
      if (position < _text.length) {
        return "'${escape(_input[position])}'";
      }
      return 'end of file';
    }

    String report(String message, String source, int start) {
      if (start < 0 || start > source.length) {
        start = null;
      }

      final sb = StringBuffer();
      sb.write(message);
      var line = 0;
      var col = 0;
      var lineStart = 0;
      var started = false;
      if (start != null) {
        for (var i = 0; i < source.length; i++) {
          final c = source.codeUnitAt(i);
          if (!started) {
            started = true;
            lineStart = i;
            line++;
            col = 1;
          } else {
            col++;
          }
          if (c == 10) {
            started = false;
          }
          if (start == i) {
            break;
          }
        }
      }

      if (start == null) {
        sb.writeln('.');
      } else if (line == 0 || start == source.length) {
        sb.write(' (at offset ');
        sb.write(start);
        sb.writeln('):');
      } else {
        sb.write(' (at line ');
        sb.write(line);
        sb.write(', column ');
        sb.write(col);
        sb.writeln('):');
      }

      List<int> escape(int c) {
        switch (c) {
          case 9:
            return [92, 116];
          case 10:
            return [92, 110];
          case 13:
            return [92, 114];
          default:
            return [c];
        }
      }

      const max = 70;
      if (start != null) {
        final c1 = <int>[];
        final c2 = <int>[];
        final half = max ~/ 2;
        var cr = false;
        for (var i = start; i >= lineStart && c1.length < half; i--) {
          if (i == source.length) {
            c2.insert(0, 94);
          } else {
            final c = source.codeUnitAt(i);
            final escaped = escape(c);
            c1.insertAll(0, escaped);
            if (c == 10) {
              cr = true;
            }

            final r = i == start ? 94 : 32;
            for (var k = 0; k < escaped.length; k++) {
              c2.insert(0, r);
            }
          }
        }

        for (var i = start + 1;
            i < source.length && c1.length < max && !cr;
            i++) {
          final c = source.codeUnitAt(i);
          final escaped = escape(c);
          c1.addAll(escaped);
          if (c == 10) {
            break;
          }
        }

        final text1 = String.fromCharCodes(c1);
        final text2 = String.fromCharCodes(c2);
        sb.writeln(text1);
        sb.writeln(text2);
      }

      return sb.toString();
    }

    final temp = _expected.toList();
    temp.sort((e1, e2) => e1.compareTo(e2));
    final expected = temp.toSet();
    final hasMalformed = false;
    if (expected.isNotEmpty) {
      if (!hasMalformed) {
        final sb = StringBuffer();
        sb.write('Expected ');
        sb.write(expected.join(', '));
        sb.write(' but found ');
        sb.write(getc(_error));
        final title = sb.toString();
        final message = report(title, _text, _error);
        error = FormatException(message);
      } else {
        final reason = _error == _text.length ? 'Unterminated' : 'Malformed';
        final sb = StringBuffer();
        sb.write(reason);
        sb.write(' ');
        sb.write(expected.join(', '));
        final title = sb.toString();
        final message = report(title, _text, _error);
        error = FormatException(message);
      }
    } else {
      final sb = StringBuffer();
      sb.write('Unexpected character ');
      sb.write(getc(_error));
      final title = sb.toString();
      final message = report(title, _text, _error);
      error = FormatException(message);
    }
  }

  void _fail(List<String> expected) {
    if (_error < _failure) {
      _error = _failure;
      _expected = [];
    }
    if (_error == _failure) {
      _expected.addAll(expected);
    }
  }

  void _failAt(int pos, List<String> expected) {
    _success = false;
    _failure = _pos;
    if (_error <= _failure) {
      _fail(expected);
    }
  }

  int _matchChar(int c) {
    int result;
    if (c == _c) {
      _success = true;
      _c = _input[_pos += _c <= 0xffff ? 1 : 2];
      result = c;
    } else {
      _success = false;
      _failure = _pos;
    }

    return result;
  }

  int _matchRanges(List<int> ranges) {
    int result;
    _success = false;
    for (var i = 0; i < ranges.length; i += 2) {
      if (ranges[i] <= _c) {
        if (ranges[i + 1] >= _c) {
          result = _c;
          _c = _input[_pos += _c <= 0xffff ? 1 : 2];
          _success = true;
          break;
        }
      } else {
        break;
      }
    }

    if (!_success) {
      _failure = _pos;
    }

    return result;
  }

  String _matchString(String text) {
    String result;
    final length = text.length;
    final rest = _text.length - _pos;
    final count = length > rest ? rest : length;
    var pos = _pos;
    var i = 0;
    for (; i < count; i++, pos++) {
      if (text.codeUnitAt(i) != _text.codeUnitAt(pos)) {
        break;
      }
    }

    if (_success = i == length) {
      _c = _input[_pos += length];
      result = text;
    } else {
      _failure = _pos + i;
    }

    return result;
  }

  bool _memoized(int id, bool productive) {
    final memos = _memos[_pos];
    if (memos != null) {
      for (var i = 0; i < memos.length; i++) {
        final memo = memos[i];
        if (memo.id == id && memo.productive == productive) {
          _pos = memo.pos;
          _mresult = memo.result;
          _success = memo.success;
          _c = _input[_pos];
          return true;
        }
      }
    }

    return false;
  }

  void _memoize(int id, int pos, bool productive, result) {
    var memos = _memos[pos];
    if (memos == null) {
      memos = [];
      _memos[pos] = memos;
    }

    final memo = _Memo(
      id: id,
      pos: _pos,
      productive: productive,
      result: result,
      success: _success,
    );

    memos.add(memo);
  }

  void _reset() {
    _c = _input[0];
    _error = 0;
    _expected = [];
    _failure = -1;
    _memos = [];
    _memos.length = _input.length + 1;
    _pos = 0;
    _predicate = false;
    _success = false;
  }

  List<int> _toRunes(String source) {
    final length = source.length;
    final result = List<int>(length + 1);
    for (var pos = 0; pos < length;) {
      int c;
      final start = pos;
      final leading = source.codeUnitAt(pos++);
      if ((leading & 0xFC00) == 0xD800 && pos < length) {
        final trailing = source.codeUnitAt(pos);
        if ((trailing & 0xFC00) == 0xDC00) {
          c = 0x10000 + ((leading & 0x3FF) << 10) + (trailing & 0x3FF);
          pos++;
        } else {
          c = leading;
        }
      } else {
        c = leading;
      }

      result[start] = c;
    }

    result[length] = 0x110000;
    return result;
  }

  dynamic _parseJson(bool $0, bool $1) {
    dynamic $2;
    final $3 = _pos;
    final $4 = _c;
    dynamic $6;
    if ($4 >= 9 && $4 <= 10 || $4 == 13 || $4 == 32) {
      _parse_leading_spaces(false, false);
    } else {
      _success = true;
    }
    final $13 = _parseValue(true, $1);
    if (_success) {
      final $14 = _c;
      if ($14 == 1114112) {
        _parse_end_of_file(false, false);
      } else {
        _failAt(_pos, const ['\'end of file\'']);
      }
      if (_success) {
        $6 = $13;
      }
    }
    if (!_success) {
      _c = $4;
      _pos = $3;
    }
    $2 = $6;
    if (!_success && _error == $3) {
      _fail(const [
        '\'false\'',
        '\'null\'',
        '\'true\'',
        '\'number\'',
        '\'string\'',
        '\'[\'',
        '\'{\''
      ]);
    }
    return $2;
  }

  dynamic _parseValue(bool $0, bool $1) {
    dynamic $2;
    final $3 = _pos;
    if ($0 && _memoized(6, $1)) {
      return _mresult as dynamic;
    }
    final $5 = _pos;
    for (;;) {
      List $6;
      final $9 = _parseArray(false, $1);
      if (_success) {
        $6 = $9;
        $2 = $6;
        break;
      }
      dynamic $10;
      final $11 = _c;
      dynamic $14;
      if ($11 == 102) {
        final $15 = _parse_false(false, $1);
        $14 = $15;
      } else {
        _failAt(_pos, const ['\'false\'']);
      }
      if (_success) {
        $10 = $14;
        $2 = $10;
        break;
      }
      dynamic $16;
      final $17 = _c;
      dynamic $20;
      if ($17 == 110) {
        final $21 = _parse_null(false, $1);
        $20 = $21;
      } else {
        _failAt(_pos, const ['\'null\'']);
      }
      if (_success) {
        $16 = $20;
        $2 = $16;
        break;
      }
      dynamic $22;
      final $23 = _c;
      dynamic $26;
      if ($23 == 116) {
        final $27 = _parse_true(false, $1);
        $26 = $27;
      } else {
        _failAt(_pos, const ['\'true\'']);
      }
      if (_success) {
        $22 = $26;
        $2 = $22;
        break;
      }
      Map<String, dynamic> $28;
      final $31 = _parseObject(false, $1);
      if (_success) {
        $28 = $31;
        $2 = $28;
        break;
      }
      num $32;
      final $33 = _c;
      num $36;
      if ($33 == 45 || $33 >= 48 && $33 <= 57) {
        final $37 = _parse_number(false, $1);
        $36 = $37;
      } else {
        _failAt(_pos, const ['\'number\'']);
      }
      if (_success) {
        $32 = $36;
        $2 = $32;
        break;
      }
      String $38;
      final $39 = _c;
      String $42;
      if ($39 == 34) {
        final $43 = _parse_string(true, $1);
        $42 = $43;
      } else {
        _failAt(_pos, const ['\'string\'']);
      }
      if (_success) {
        $38 = $42;
        $2 = $38;
        break;
      }
      break;
    }
    if (!_success && _error == $5) {
      _fail(const [
        '\'false\'',
        '\'null\'',
        '\'true\'',
        '\'number\'',
        '\'string\'',
        '\'[\'',
        '\'{\''
      ]);
    }
    if ($0) {
      _memoize(6, $3, $1, $2);
    }
    return $2;
  }

  List _parseArray(bool $0, bool $1) {
    List $2;
    final $3 = _pos;
    final $4 = _c;
    List $6;
    if ($4 == 91) {
      _parse_$LeftSquareBracket(false, false);
    } else {
      _failAt(_pos, const ['\'[\'']);
    }
    if (_success) {
      final $12 = _parseValues(false, true);
      final $13 = $12;
      final $14 = _c;
      if ($14 == 93) {
        _parse_$RightSquareBracket(false, false);
      } else {
        _failAt(_pos, const ['\']\'']);
      }
      if (_success) {
        final v = $13;
        List $$;
        $$ = v ?? [];
        $6 = $$;
      }
      if (!_success) {
        _c = $4;
        _pos = $3;
      }
    }
    $2 = $6;
    if (!_success && _error == $3) {
      _fail(const ['\'[\'']);
    }
    return $2;
  }

  List _parseValues(bool $0, bool $1) {
    List $2;
    final $3 = _pos;
    List $6;
    final $9 = _parseValue(true, true);
    if (_success) {
      List $10;
      $10 = [];
      for (;;) {
        dynamic $11;
        final $12 = _pos;
        final $15 = $1;
        $1 = true;
        dynamic $16;
        final $17 = _c;
        final $18 = _pos;
        if ($17 == 44) {
          _parse_$Comma(true, false);
        } else {
          _failAt(_pos, const ['\',\'']);
        }
        if (_success) {
          final $22 = _parseValue(false, $1);
          if (_success) {
            $16 = $22;
          } else {
            _c = $17;
            _pos = $18;
          }
        }
        $11 = $16;
        if (!_success && _error == $12) {
          _fail(const ['\',\'']);
        }
        $1 = $15;
        if (!_success) {
          _success = true;
          break;
        }
        $10.add($11);
      }
      {
        final v = $9;
        final n = $10;
        List $$;
        $$ = [v, ...n];
        $6 = $$;
      }
    }
    $2 = $6;
    if (!_success && _error == $3) {
      _fail(const [
        '\'false\'',
        '\'null\'',
        '\'true\'',
        '\'number\'',
        '\'string\'',
        '\'[\'',
        '\'{\''
      ]);
    }
    return $2;
  }

  Map<String, dynamic> _parseObject(bool $0, bool $1) {
    Map<String, dynamic> $2;
    final $3 = _pos;
    final $4 = _c;
    Map<String, dynamic> $6;
    if ($4 == 123) {
      _parse_$LeftBrace(false, false);
    } else {
      _failAt(_pos, const ['\'{\'']);
    }
    if (_success) {
      final $12 = _parseMembers(false, true);
      final $13 = $12;
      final $14 = _c;
      if ($14 == 125) {
        _parse_$RightBrace(false, false);
      } else {
        _failAt(_pos, const ['\'}\'']);
      }
      if (_success) {
        final m = $13;
        Map<String, dynamic> $$;
        $$ = <String, dynamic>{}..addEntries(m ?? []);
        $6 = $$;
      }
      if (!_success) {
        _c = $4;
        _pos = $3;
      }
    }
    $2 = $6;
    if (!_success && _error == $3) {
      _fail(const ['\'{\'']);
    }
    return $2;
  }

  List<MapEntry<String, dynamic>> _parseMembers(bool $0, bool $1) {
    List<MapEntry<String, dynamic>> $2;
    final $3 = _pos;
    List<MapEntry<String, dynamic>> $6;
    final $9 = _parseMember(false, true);
    if (_success) {
      List<MapEntry<String, dynamic>> $10;
      $10 = [];
      for (;;) {
        MapEntry<String, dynamic> $11;
        final $12 = _pos;
        final $15 = $1;
        $1 = true;
        MapEntry<String, dynamic> $16;
        final $17 = _c;
        final $18 = _pos;
        if ($17 == 44) {
          _parse_$Comma(true, false);
        } else {
          _failAt(_pos, const ['\',\'']);
        }
        if (_success) {
          final $22 = _parseMember(false, $1);
          if (_success) {
            $16 = $22;
          } else {
            _c = $17;
            _pos = $18;
          }
        }
        $11 = $16;
        if (!_success && _error == $12) {
          _fail(const ['\',\'']);
        }
        $1 = $15;
        if (!_success) {
          _success = true;
          break;
        }
        $10.add($11);
      }
      {
        final m = $9;
        final n = $10;
        List<MapEntry<String, dynamic>> $$;
        $$ = [m, ...n];
        $6 = $$;
      }
    }
    $2 = $6;
    if (!_success && _error == $3) {
      _fail(const ['\'string\'']);
    }
    return $2;
  }

  MapEntry<String, dynamic> _parseMember(bool $0, bool $1) {
    MapEntry<String, dynamic> $2;
    final $3 = _pos;
    final $4 = _c;
    MapEntry<String, dynamic> $6;
    String $10;
    if ($4 == 34) {
      final $11 = _parse_string(true, true);
      $10 = $11;
    } else {
      _failAt(_pos, const ['\'string\'']);
    }
    if (_success) {
      final $12 = _c;
      if ($12 == 58) {
        _parse_$Colon(false, false);
      } else {
        _failAt(_pos, const ['\':\'']);
      }
      if (_success) {
        final $15 = _parseValue(true, true);
        if (_success) {
          final k = $10;
          final v = $15;
          MapEntry<String, dynamic> $$;
          $$ = MapEntry(k, v);
          $6 = $$;
        }
      }
      if (!_success) {
        _c = $4;
        _pos = $3;
      }
    }
    $2 = $6;
    if (!_success && _error == $3) {
      _fail(const ['\'string\'']);
    }
    return $2;
  }

  dynamic _parse_end_of_file(bool $0, bool $1) {
    dynamic $2;
    final $3 = _pos;
    final $4 = _c;
    dynamic $7;
    final $12 = _error;
    final $13 = _expected;
    final $14 = _failure;
    final $15 = $1;
    $1 = false;
    if (_c >= 0 && _c <= 1114111) {
      _success = true;
      _c = _input[_pos += _c <= 65535 ? 1 : 2];
    } else {
      _success = false;
      _failure = _pos;
    }
    _success = !_success;
    _c = $4;
    _pos = $3;
    _error = $12;
    _expected = $13;
    _failure = $14;
    $1 = $15;
    var $17;
    if (_success) {
      $7 = $17;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'end of file\'']);
    }
    return $2;
  }

  dynamic _parse_false(bool $0, bool $1) {
    dynamic $2;
    dynamic $7;
    if (_c == 102) {
      _matchString('false');
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      {
        dynamic $$;
        $$ = false;
        $7 = $$;
      }
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'false\'']);
    }
    return $2;
  }

  List<int> _parse_leading_spaces(bool $0, bool $1) {
    List<int> $2;
    $2 = _parse$$spacing(false, $1);
    if (!_success && _error <= _failure) {
      _fail(const ['\'leading spaces\'']);
    }
    return $2;
  }

  dynamic _parse_null(bool $0, bool $1) {
    dynamic $2;
    dynamic $7;
    if (_c == 110) {
      _matchString('null');
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      {
        dynamic $$;
        $$ = null;
        $7 = $$;
      }
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'null\'']);
    }
    return $2;
  }

  dynamic _parse_true(bool $0, bool $1) {
    dynamic $2;
    dynamic $7;
    if (_c == 116) {
      _matchString('true');
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      {
        dynamic $$;
        $$ = true;
        $7 = $$;
      }
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'true\'']);
    }
    return $2;
  }

  String _parse_string(bool $0, bool $1) {
    String $2;
    final $3 = _pos;
    if ($0 && _memoized(73, $1)) {
      return _mresult as String;
    }
    final $4 = _c;
    final $5 = _pos;
    String $7;
    if (_c == 34) {
      _success = true;
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      List<int> $11;
      $11 = [];
      for (;;) {
        final $12 = _c;
        int $13;
        if ($12 >= 32 && $12 <= 33 || $12 >= 35 && $12 <= 1114111) {
          final $14 = _parse$$char(false, true);
          $13 = $14;
        } else {
          _failAt(_pos, const []);
        }
        if (!_success) {
          _success = true;
          break;
        }
        $11.add($13);
      }
      if (_c == 34) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        final $16 = _c;
        if ($16 >= 9 && $16 <= 10 || $16 == 13 || $16 == 32) {
          _parse$$spacing(false, false);
        } else {
          _success = true;
        }
        {
          final c = $11;
          String $$;
          $$ = String.fromCharCodes(c);
          $7 = $$;
        }
      }
      if (!_success) {
        _c = $4;
        _pos = $5;
      }
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'string\'']);
    }
    if ($0) {
      _memoize(73, $3, $1, $2);
    }
    return $2;
  }

  num _parse_number(bool $0, bool $1) {
    num $2;
    final $3 = _pos;
    num $7;
    String $10;
    final $12 = $1;
    $1 = false;
    final $18 = $1;
    $1 = true;
    if (_c == 45) {
      _success = true;
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    final $25 = _pos;
    final $26 = _c;
    var $28 = _pos;
    final $29 = $1;
    $1 = false;
    for (;;) {
      if (_c == 48) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if ($28 < _failure) {
        $28 = _failure;
      }
      if (_success) {
        break;
      }
      if (_c >= 49 && _c <= 57) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        for (;;) {
          if (_c >= 48 && _c <= 57) {
            _success = true;
            _c = _input[++_pos];
          } else {
            _success = false;
            _failure = _pos;
          }
          if (!_success) {
            _success = true;
            break;
          }
        }
      }
      if ($28 < _failure) {
        $28 = _failure;
      }
      if (_success) {
        break;
      }
      _c = $26;
      _pos = $25;
      _failure = $28;
      break;
    }
    $1 = $29;
    if (_success) {
      final $45 = $1;
      $1 = false;
      final $47 = _c;
      final $48 = _pos;
      if (_c == 46) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        var $51 = false;
        for (;;) {
          if (_c >= 48 && _c <= 57) {
            _success = true;
            _c = _input[++_pos];
          } else {
            _success = false;
            _failure = _pos;
          }
          if (!_success) {
            _success = $51;
            break;
          }
          $51 = true;
        }
        if (!_success) {
          _c = $47;
          _pos = $48;
        }
      }
      $1 = $45;
      final $59 = $1;
      $1 = false;
      final $61 = _c;
      final $62 = _pos;
      if (_c == 69 || _c == 101) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        if (_c == 43 || _c == 45) {
          _success = true;
          _c = _input[++_pos];
        } else {
          _success = false;
          _failure = _pos;
        }
        var $67 = false;
        for (;;) {
          if (_c >= 48 && _c <= 57) {
            _success = true;
            _c = _input[++_pos];
          } else {
            _success = false;
            _failure = _pos;
          }
          if (!_success) {
            _success = $67;
            break;
          }
          $67 = true;
        }
        if (!_success) {
          _c = $61;
          _pos = $62;
        }
      }
      $1 = $59;
      _success = true;
    }
    $1 = $18;
    $1 = $12;
    $10 = _text.substring($3, _pos);
    if (_success) {
      final $70 = _c;
      if ($70 >= 9 && $70 <= 10 || $70 == 13 || $70 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      {
        final n = $10;
        num $$;
        $$ = num.parse(n);
        $7 = $$;
      }
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'number\'']);
    }
    return $2;
  }

  String _parse_$LeftBrace(bool $0, bool $1) {
    String $2;
    String $7;
    String $10;
    if (_c == 123) {
      _success = true;
      $10 = '{';
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      $7 = $10;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'{\'']);
    }
    return $2;
  }

  String _parse_$RightBrace(bool $0, bool $1) {
    String $2;
    String $7;
    String $10;
    if (_c == 125) {
      _success = true;
      $10 = '}';
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      $7 = $10;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'}\'']);
    }
    return $2;
  }

  String _parse_$LeftSquareBracket(bool $0, bool $1) {
    String $2;
    String $7;
    String $10;
    if (_c == 91) {
      _success = true;
      $10 = '[';
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      $7 = $10;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\'[\'']);
    }
    return $2;
  }

  String _parse_$RightSquareBracket(bool $0, bool $1) {
    String $2;
    String $7;
    String $10;
    if (_c == 93) {
      _success = true;
      $10 = ']';
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      $7 = $10;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\']\'']);
    }
    return $2;
  }

  String _parse_$Comma(bool $0, bool $1) {
    String $2;
    final $3 = _pos;
    if ($0 && _memoized(125, $1)) {
      return _mresult as String;
    }
    String $7;
    String $10;
    if (_c == 44) {
      _success = true;
      $10 = ',';
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      $7 = $10;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\',\'']);
    }
    if ($0) {
      _memoize(125, $3, $1, $2);
    }
    return $2;
  }

  String _parse_$Colon(bool $0, bool $1) {
    String $2;
    String $7;
    String $10;
    if (_c == 58) {
      _success = true;
      $10 = ':';
      _c = _input[++_pos];
    } else {
      _success = false;
      _failure = _pos;
    }
    if (_success) {
      final $11 = _c;
      if ($11 >= 9 && $11 <= 10 || $11 == 13 || $11 == 32) {
        _parse$$spacing(false, false);
      } else {
        _success = true;
      }
      $7 = $10;
    }
    $2 = $7;
    if (!_success && _error <= _failure) {
      _fail(const ['\':\'']);
    }
    return $2;
  }

  int _parse$$char(bool $0, bool $1) {
    int $2;
    final $3 = _pos;
    final $4 = _c;
    for (;;) {
      int $6;
      final $7 = _c;
      final $8 = _pos;
      if (_c == 92) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        final $10 = _c;
        int $11;
        if ($10 == 34 ||
            $10 == 47 ||
            $10 == 92 ||
            $10 == 98 ||
            $10 == 102 ||
            $10 == 110 ||
            $10 == 114 ||
            $10 >= 116 && $10 <= 117) {
          final $12 = _parse$$escaped(false, $1);
          $11 = $12;
        } else {
          _failAt(_pos, const []);
        }
        if (_success) {
          $6 = $11;
        } else {
          _c = $7;
          _pos = $8;
        }
      }
      if (_success) {
        $2 = $6;
        break;
      }
      _c = $4;
      _pos = $3;
      int $13;
      final $14 = _c;
      int $17;
      if ($14 >= 32 && $14 <= 33 ||
          $14 >= 35 && $14 <= 91 ||
          $14 >= 93 && $14 <= 1114111) {
        final $18 = _parse$$unescaped(false, $1);
        $17 = $18;
      } else {
        _failAt(_pos, const []);
      }
      if (_success) {
        $13 = $17;
        $2 = $13;
        break;
      }
      break;
    }
    return $2;
  }

  int _parse$$escaped(bool $0, bool $1) {
    int $2;
    final $3 = _pos;
    final $4 = _c;
    for (;;) {
      int $6;
      int $9;
      if (_c == 34) {
        _success = true;
        $9 = _c;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        $6 = $9;
        $2 = $6;
        break;
      }
      int $10;
      int $13;
      if (_c == 92) {
        _success = true;
        $13 = _c;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        $10 = $13;
        $2 = $10;
        break;
      }
      int $14;
      int $17;
      if (_c == 47) {
        _success = true;
        $17 = _c;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        $14 = $17;
        $2 = $14;
        break;
      }
      int $18;
      if (_c == 98) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = 0x8;
        $18 = $$;
      }
      if (_success) {
        $2 = $18;
        break;
      }
      int $22;
      if (_c == 102) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = 0xC;
        $22 = $$;
      }
      if (_success) {
        $2 = $22;
        break;
      }
      int $26;
      if (_c == 110) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = 0xA;
        $26 = $$;
      }
      if (_success) {
        $2 = $26;
        break;
      }
      int $30;
      if (_c == 114) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = 0xD;
        $30 = $$;
      }
      if (_success) {
        $2 = $30;
        break;
      }
      int $34;
      if (_c == 116) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = 0x9;
        $34 = $$;
      }
      if (_success) {
        $2 = $34;
        break;
      }
      int $38;
      final $39 = _c;
      final $40 = _pos;
      if (_c == 117) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        final $42 = _c;
        int $43;
        if ($42 >= 48 && $42 <= 57 ||
            $42 >= 65 && $42 <= 70 ||
            $42 >= 97 && $42 <= 102) {
          final $44 = _parse$$hexdig4(false, $1);
          $43 = $44;
        } else {
          _failAt(_pos, const []);
        }
        if (_success) {
          $38 = $43;
        } else {
          _c = $39;
          _pos = $40;
        }
      }
      if (_success) {
        $2 = $38;
        break;
      }
      _c = $4;
      _pos = $3;
      break;
    }
    return $2;
  }

  int _parse$$hexdig4(bool $0, bool $1) {
    int $2;
    final $3 = _pos;
    final $4 = _c;
    int $6;
    int $10;
    if ($4 >= 48 && $4 <= 57 || $4 >= 65 && $4 <= 70 || $4 >= 97 && $4 <= 102) {
      final $11 = _parse$$hexdig(false, true);
      $10 = $11;
    } else {
      _failAt(_pos, const []);
    }
    if (_success) {
      final $12 = _c;
      int $13;
      if ($12 >= 48 && $12 <= 57 ||
          $12 >= 65 && $12 <= 70 ||
          $12 >= 97 && $12 <= 102) {
        final $14 = _parse$$hexdig(false, true);
        $13 = $14;
      } else {
        _failAt(_pos, const []);
      }
      if (_success) {
        final $15 = _c;
        int $16;
        if ($15 >= 48 && $15 <= 57 ||
            $15 >= 65 && $15 <= 70 ||
            $15 >= 97 && $15 <= 102) {
          final $17 = _parse$$hexdig(false, true);
          $16 = $17;
        } else {
          _failAt(_pos, const []);
        }
        if (_success) {
          final $18 = _c;
          int $19;
          if ($18 >= 48 && $18 <= 57 ||
              $18 >= 65 && $18 <= 70 ||
              $18 >= 97 && $18 <= 102) {
            final $20 = _parse$$hexdig(false, true);
            $19 = $20;
          } else {
            _failAt(_pos, const []);
          }
          if (_success) {
            final a = $10;
            final b = $13;
            final c = $16;
            final d = $19;
            int $$;
            $$ = a * 0xfff + b * 0xff + c * 0xf + d;
            $6 = $$;
          }
        }
      }
      if (!_success) {
        _c = $4;
        _pos = $3;
      }
    }
    $2 = $6;
    return $2;
  }

  int _parse$$hexdig(bool $0, bool $1) {
    int $2;
    for (;;) {
      int $6;
      if (_c >= 97 && _c <= 102) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = $$ - 97;
        $6 = $$;
      }
      if (_success) {
        $2 = $6;
        break;
      }
      int $10;
      if (_c >= 65 && _c <= 70) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = $$ - 65;
        $10 = $$;
      }
      if (_success) {
        $2 = $10;
        break;
      }
      int $14;
      if (_c >= 48 && _c <= 57) {
        _success = true;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        int $$;
        $$ = $$ - 48;
        $14 = $$;
      }
      if (_success) {
        $2 = $14;
        break;
      }
      break;
    }
    return $2;
  }

  int _parse$$unescaped(bool $0, bool $1) {
    int $2;
    for (;;) {
      int $6;
      int $9;
      if (_c >= 32 && _c <= 33) {
        _success = true;
        $9 = _c;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        $6 = $9;
        $2 = $6;
        break;
      }
      int $10;
      int $13;
      if (_c >= 35 && _c <= 91) {
        _success = true;
        $13 = _c;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        $10 = $13;
        $2 = $10;
        break;
      }
      int $14;
      int $17;
      if (_c >= 93 && _c <= 1114111) {
        _success = true;
        $17 = _c;
        _c = _input[_pos += _c <= 65535 ? 1 : 2];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (_success) {
        $14 = $17;
        $2 = $14;
        break;
      }
      break;
    }
    return $2;
  }

  List<int> _parse$$spacing(bool $0, bool $1) {
    List<int> $2;
    List<int> $9;
    if ($1) {
      $9 = [];
    }
    for (;;) {
      int $10;
      if (_c >= 9 && _c <= 10 || _c == 13 || _c == 32) {
        _success = true;
        $10 = _c;
        _c = _input[++_pos];
      } else {
        _success = false;
        _failure = _pos;
      }
      if (!_success) {
        _success = true;
        break;
      }
      if ($1) {
        $9.add($10);
      }
    }
    $2 = $9;
    return $2;
  }
}

class _Memo {
  final int id;
  final int pos;
  final bool productive;
  final result;
  final bool success;

  _Memo({
    this.id,
    this.pos,
    this.productive,
    this.result,
    this.success,
  });
}

// ignore_for_file: unused_element
// ignore_for_file: unused_field

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  peg2: ^0.1.34

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:peg2/code_builder.dart';
import 'package:peg2/common_generators.dart';
import 'package:peg2/expressions.dart';
import 'package:peg2/expression_analyzers.dart';
import 'package:peg2/finite_automaton.dart';
import 'package:peg2/general_parser_generator.dart';
import 'package:peg2/grammar.dart';
import 'package:peg2/grammar_analyzers.dart';
import 'package:peg2/grammar_fa_analyzers.dart';
import 'package:peg2/operations.dart';
import 'package:peg2/operation_generators.dart';
import 'package:peg2/operation_optimizers.dart';
import 'package:peg2/operation_transformers.dart';
import 'package:peg2/operation_utils.dart';
import 'package:peg2/parser_generator.dart';
import 'package:peg2/utils.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
99
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
50
Learn more about scoring.

We analyzed this package on Jul 11, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.15

Analysis suggestions

Package not compatible with runtime flutter-web on Web

Because:

  • package:peg2/common_generators.dart that imports:
  • package:peg2/parser_generator.dart that imports:
  • package:dart_style/dart_style.dart that imports:
  • package:dart_style/src/exceptions.dart that imports:
  • package:analyzer/error/error.dart that imports:
  • package:analyzer/src/generated/source.dart that imports:
  • package:analyzer/src/generated/source_io.dart that imports:
  • package:analyzer/src/generated/java_io.dart that imports:
  • dart:io

Package not compatible with runtime js

Because:

  • package:peg2/common_generators.dart that imports:
  • package:peg2/parser_generator.dart that imports:
  • package:dart_style/dart_style.dart that imports:
  • package:dart_style/src/exceptions.dart that imports:
  • package:analyzer/error/error.dart that imports:
  • package:analyzer/src/generated/source.dart that imports:
  • package:analyzer/src/generated/source_io.dart that imports:
  • package:analyzer/src/generated/java_io.dart that imports:
  • dart:io

Health issues and suggestions

Document public APIs. (-0.88 points)

967 out of 971 API elements have no dartdoc comment.Providing good documentation for libraries, classes, functions, and other API elements improves code readability and helps developers find and use your API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
args ^1.6.0 1.6.0
dart_style ^1.3.6 1.3.6
enumerable ^0.1.3 0.1.3
lists ^0.1.6 0.1.6
meta ^1.1.8 1.2.2 1.3.0-nullsafety
path ^1.7.0 1.7.0
strings ^0.1.2 0.1.2
Transitive dependencies
_fe_analyzer_shared 5.0.0
analyzer 0.39.12
async 2.4.2
charcode 1.1.3
collection 1.14.13 1.15.0-nullsafety
convert 2.1.1
crypto 2.1.5
csslib 0.16.1
glob 1.2.0
html 0.14.0+3
js 0.6.2
node_interop 1.1.1
node_io 1.1.1
package_config 1.9.3
pub_semver 1.4.4
source_span 1.7.0
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.2.0 1.3.0-nullsafety
unicode 0.2.4
watcher 0.9.7+15
yaml 2.2.1
Dev dependencies
pedantic ^1.9.0 1.9.2
test ^1.14.3