peg2 0.2.0 peg2: ^0.2.0 copied to clipboard
PEG+ (Parsing expression grammar) parser source code generator, command line tool.
// Generated by 'peg2'
// https://pub.dev/packages/peg2
void main() {
final text = '''
{"rocket": "🚀 flies to the stars"}
''';
final parser = ExampleParser();
final result = parser.parse(text);
if (!parser.ok) {
throw parser.error!;
}
print(result);
}
class ExampleParser {
static const int _eof = 1114112;
FormatException? error;
int _failStart = -1;
List _failures = [];
bool ok = false;
int _ch = 0;
int _failPos = -1;
int _pos = 0;
String _source = '';
dynamic? parse(String source) {
_source = source;
_reset();
final result = parseJson();
if (!ok) {
_buildError();
}
return result;
}
dynamic? parseJson() {
dynamic? $0;
final $1 = _ch;
final $2 = _pos;
dynamic? $3;
parse_leading_spaces();
ok = true;
final $4 = parseValue();
if (ok) {
parse_end_of_file();
if (ok) {
$3 = $4;
}
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
dynamic? parseValue() {
dynamic? $0;
final $1 = _ch;
final $2 = _pos;
while (true) {
List? $3;
final $4 = parseArray();
if (ok) {
$3 = $4;
}
if (ok) {
$0 = $3;
break;
}
_pos = $2;
_ch = $1;
dynamic? $5;
final $6 = parse_false();
if (ok) {
$5 = $6;
}
if (ok) {
$0 = $5;
break;
}
_pos = $2;
_ch = $1;
dynamic? $7;
final $8 = parse_null();
if (ok) {
$7 = $8;
}
if (ok) {
$0 = $7;
break;
}
_pos = $2;
_ch = $1;
dynamic? $9;
final $10 = parse_true();
if (ok) {
$9 = $10;
}
if (ok) {
$0 = $9;
break;
}
_pos = $2;
_ch = $1;
Map<String, dynamic>? $11;
final $12 = parseObject();
if (ok) {
$11 = $12;
}
if (ok) {
$0 = $11;
break;
}
_pos = $2;
_ch = $1;
num? $13;
final $14 = parse_number();
if (ok) {
$13 = $14;
}
if (ok) {
$0 = $13;
break;
}
_pos = $2;
_ch = $1;
String? $15;
final $16 = parse_string();
if (ok) {
$15 = $16;
}
if (ok) {
$0 = $15;
break;
}
_pos = $2;
_ch = $1;
break;
}
return $0;
}
List? parseArray() {
List? $0;
final $1 = _ch;
final $2 = _pos;
List? $3;
parse_$LeftSquareBracket();
if (ok) {
final $5 = parseValues();
final $4 = $5;
ok = true;
parse_$RightSquareBracket();
if (ok) {
final v = $4;
late List $$;
$$ = v ?? [];
$3 = $$;
}
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
List? parseValues() {
List? $0;
final $1 = _ch;
final $2 = _pos;
List? $3;
final $4 = parseValue();
if (ok) {
final $5 = [];
while (true) {
dynamic? $6;
final $7 = _ch;
final $8 = _pos;
dynamic? $9;
parse_$Comma();
if (ok) {
final $10 = parseValue();
if (ok) {
$9 = $10;
}
}
if (ok) {
$6 = $9;
} else {
_pos = $8;
_ch = $7;
break;
}
$5.add($6);
}
ok = true;
final v = $4;
final n = $5;
late List $$;
$$ = [v, ...n];
$3 = $$;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
Map<String, dynamic>? parseObject() {
Map<String, dynamic>? $0;
final $1 = _ch;
final $2 = _pos;
Map<String, dynamic>? $3;
parse_$LeftBrace();
if (ok) {
final $5 = parseMembers();
final $4 = $5;
ok = true;
parse_$RightBrace();
if (ok) {
final m = $4;
late Map<String, dynamic> $$;
$$ = <String, dynamic>{}..addEntries(m ?? []);
$3 = $$;
}
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
List<MapEntry<String, dynamic>>? parseMembers() {
List<MapEntry<String, dynamic>>? $0;
final $1 = _ch;
final $2 = _pos;
List<MapEntry<String, dynamic>>? $3;
final $4 = parseMember();
if (ok) {
final $5 = <MapEntry<String, dynamic>>[];
while (true) {
MapEntry<String, dynamic>? $6;
final $7 = _ch;
final $8 = _pos;
MapEntry<String, dynamic>? $9;
parse_$Comma();
if (ok) {
final $10 = parseMember();
if (ok) {
$9 = $10;
}
}
if (ok) {
$6 = $9;
} else {
_pos = $8;
_ch = $7;
break;
}
$5.add($6!);
}
ok = true;
final m = $4!;
final n = $5;
late List<MapEntry<String, dynamic>> $$;
$$ = [m, ...n];
$3 = $$;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
MapEntry<String, dynamic>? parseMember() {
MapEntry<String, dynamic>? $0;
final $1 = _ch;
final $2 = _pos;
MapEntry<String, dynamic>? $3;
final $4 = parse_string();
if (ok) {
parse_$Colon();
if (ok) {
final $5 = parseValue();
if (ok) {
final k = $4!;
final v = $5;
late MapEntry<String, dynamic> $$;
$$ = MapEntry(k, v);
$3 = $$;
}
}
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
dynamic? parse_end_of_file() {
_failPos = -1;
dynamic? $0;
final $1 = _ch;
final $2 = _pos;
dynamic? $3;
final $5 = _ch;
final $6 = _pos;
_matchAny();
final $4 = null;
_ch = $5;
_pos = $6;
ok = !ok;
if (ok) {
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'end of file\'');
}
return $0;
}
dynamic? parse_false() {
_failPos = -1;
dynamic? $0;
final $1 = _ch;
final $2 = _pos;
dynamic? $3;
_matchString('false');
if (ok) {
parse$$spacing();
var $$;
$$ = false;
$3 = $$;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'false\'');
}
return $0;
}
List<int>? parse_leading_spaces() {
_failPos = -1;
List<int>? $0;
final $1 = _ch;
final $2 = _pos;
List<int>? $3;
final $4 = parse$$spacing();
$3 = $4;
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'leading spaces\'');
}
return $0;
}
dynamic? parse_null() {
_failPos = -1;
dynamic? $0;
final $1 = _ch;
final $2 = _pos;
dynamic? $3;
_matchString('null');
if (ok) {
parse$$spacing();
var $$;
$$ = null;
$3 = $$;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'null\'');
}
return $0;
}
dynamic? parse_true() {
_failPos = -1;
dynamic? $0;
final $1 = _ch;
final $2 = _pos;
dynamic? $3;
_matchString('true');
if (ok) {
parse$$spacing();
var $$;
$$ = true;
$3 = $$;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'true\'');
}
return $0;
}
String? parse_string() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
_matchChar(34, '"');
if (ok) {
final $4 = <int>[];
while (true) {
final $5 = parse$$char();
if (!ok) {
break;
}
$4.add($5!);
}
ok = true;
_matchChar(34, '"');
if (ok) {
parse$$spacing();
final c = $4;
late String $$;
$$ = String.fromCharCodes(c);
$3 = $$;
}
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'string\'');
}
return $0;
}
num? parse_number() {
_failPos = -1;
num? $0;
final $1 = _ch;
final $2 = _pos;
num? $3;
String? $4;
final $5 = _pos;
final $6 = _ch;
final $7 = _pos;
_matchChar(45, 45);
ok = true;
final $8 = _ch;
final $9 = _pos;
while (true) {
_matchChar(48, 48);
if (ok) {
break;
}
_pos = $9;
_ch = $8;
const $10 = [49, 57];
_matchRange($10);
if (ok) {
while (true) {
const $11 = [48, 57];
_matchRange($11);
if (!ok) {
break;
}
}
ok = true;
}
if (ok) {
break;
}
_pos = $9;
_ch = $8;
break;
}
if (ok) {
final $12 = _ch;
final $13 = _pos;
_matchChar(46, 46);
if (ok) {
var $14 = 0;
while (true) {
const $15 = [48, 57];
_matchRange($15);
if (!ok) {
break;
}
$14++;
}
ok = $14 != 0;
}
if (!ok) {
_pos = $13;
_ch = $12;
}
ok = true;
final $16 = _ch;
final $17 = _pos;
const $18 = [69, 69, 101, 101];
_matchRange($18);
if (ok) {
const $19 = [43, 43, 45, 45];
_matchRange($19);
ok = true;
var $20 = 0;
while (true) {
const $21 = [48, 57];
_matchRange($21);
if (!ok) {
break;
}
$20++;
}
ok = $20 != 0;
}
if (!ok) {
_pos = $17;
_ch = $16;
}
ok = true;
}
if (!ok) {
_pos = $7;
_ch = $6;
}
if (ok) {
$4 = _source.substring($5, _pos);
}
if (ok) {
parse$$spacing();
final n = $4!;
late num $$;
$$ = num.parse(n);
$3 = $$;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'number\'');
}
return $0;
}
String? parse_$LeftBrace() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
final $4 = _matchChar(123, '{');
if (ok) {
parse$$spacing();
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'{\'');
}
return $0;
}
String? parse_$RightBrace() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
final $4 = _matchChar(125, '}');
if (ok) {
parse$$spacing();
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'}\'');
}
return $0;
}
String? parse_$LeftSquareBracket() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
final $4 = _matchChar(91, '[');
if (ok) {
parse$$spacing();
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\'[\'');
}
return $0;
}
String? parse_$RightSquareBracket() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
final $4 = _matchChar(93, ']');
if (ok) {
parse$$spacing();
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\']\'');
}
return $0;
}
String? parse_$Comma() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
final $4 = _matchChar(44, ',');
if (ok) {
parse$$spacing();
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\',\'');
}
return $0;
}
String? parse_$Colon() {
_failPos = -1;
String? $0;
final $1 = _ch;
final $2 = _pos;
String? $3;
final $4 = _matchChar(58, ':');
if (ok) {
parse$$spacing();
$3 = $4;
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
_fail('\':\'');
}
return $0;
}
int? parse$$char() {
int? $0;
final $1 = _ch;
final $2 = _pos;
while (true) {
int? $3;
_matchChar(92, 92);
if (ok) {
final $4 = parse$$escaped();
if (ok) {
$3 = $4;
}
}
if (ok) {
$0 = $3;
break;
}
_pos = $2;
_ch = $1;
int? $5;
final $6 = parse$$unescaped();
if (ok) {
$5 = $6;
}
if (ok) {
$0 = $5;
break;
}
_pos = $2;
_ch = $1;
break;
}
return $0;
}
int? parse$$escaped() {
int? $0;
final $1 = _ch;
final $2 = _pos;
while (true) {
int? $3;
final $4 = _matchChar(34, 34);
if (ok) {
$3 = $4;
}
if (ok) {
$0 = $3;
break;
}
_pos = $2;
_ch = $1;
int? $5;
final $6 = _matchChar(92, 92);
if (ok) {
$5 = $6;
}
if (ok) {
$0 = $5;
break;
}
_pos = $2;
_ch = $1;
int? $7;
final $8 = _matchChar(47, 47);
if (ok) {
$7 = $8;
}
if (ok) {
$0 = $7;
break;
}
_pos = $2;
_ch = $1;
int? $9;
_matchChar(98, 98);
if (ok) {
late int $$;
$$ = 0x8;
$9 = $$;
}
if (ok) {
$0 = $9;
break;
}
_pos = $2;
_ch = $1;
int? $10;
_matchChar(102, 102);
if (ok) {
late int $$;
$$ = 0xC;
$10 = $$;
}
if (ok) {
$0 = $10;
break;
}
_pos = $2;
_ch = $1;
int? $11;
_matchChar(110, 110);
if (ok) {
late int $$;
$$ = 0xA;
$11 = $$;
}
if (ok) {
$0 = $11;
break;
}
_pos = $2;
_ch = $1;
int? $12;
_matchChar(114, 114);
if (ok) {
late int $$;
$$ = 0xD;
$12 = $$;
}
if (ok) {
$0 = $12;
break;
}
_pos = $2;
_ch = $1;
int? $13;
_matchChar(116, 116);
if (ok) {
late int $$;
$$ = 0x9;
$13 = $$;
}
if (ok) {
$0 = $13;
break;
}
_pos = $2;
_ch = $1;
int? $14;
_matchChar(117, 117);
if (ok) {
final $15 = parse$$hexdig4();
if (ok) {
$14 = $15;
}
}
if (ok) {
$0 = $14;
break;
}
_pos = $2;
_ch = $1;
break;
}
return $0;
}
int? parse$$hexdig4() {
int? $0;
final $1 = _ch;
final $2 = _pos;
int? $3;
final $4 = parse$$hexdig();
if (ok) {
final $5 = parse$$hexdig();
if (ok) {
final $6 = parse$$hexdig();
if (ok) {
final $7 = parse$$hexdig();
if (ok) {
final a = $4!;
final b = $5!;
final c = $6!;
final d = $7!;
late int $$;
$$ = a * 0xfff + b * 0xff + c * 0xf + d;
$3 = $$;
}
}
}
}
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
int? parse$$hexdig() {
int? $0;
final $1 = _ch;
final $2 = _pos;
while (true) {
int? $3;
const $5 = [97, 102];
final $4 = _matchRange($5);
if (ok) {
final v = $4!;
late int $$;
$$ = v - 97;
$3 = $$;
}
if (ok) {
$0 = $3;
break;
}
_pos = $2;
_ch = $1;
int? $6;
const $8 = [65, 70];
final $7 = _matchRange($8);
if (ok) {
final v = $7!;
late int $$;
$$ = v - 65;
$6 = $$;
}
if (ok) {
$0 = $6;
break;
}
_pos = $2;
_ch = $1;
int? $9;
const $11 = [48, 57];
final $10 = _matchRange($11);
if (ok) {
final v = $10!;
late int $$;
$$ = v - 48;
$9 = $$;
}
if (ok) {
$0 = $9;
break;
}
_pos = $2;
_ch = $1;
break;
}
return $0;
}
int? parse$$unescaped() {
int? $0;
final $1 = _ch;
final $2 = _pos;
while (true) {
int? $3;
const $5 = [32, 33];
final $4 = _matchRange($5);
if (ok) {
$3 = $4;
}
if (ok) {
$0 = $3;
break;
}
_pos = $2;
_ch = $1;
int? $6;
const $8 = [35, 91];
final $7 = _matchRange($8);
if (ok) {
$6 = $7;
}
if (ok) {
$0 = $6;
break;
}
_pos = $2;
_ch = $1;
int? $9;
const $11 = [93, 1114111];
final $10 = _matchRange($11);
if (ok) {
$9 = $10;
}
if (ok) {
$0 = $9;
break;
}
_pos = $2;
_ch = $1;
break;
}
return $0;
}
List<int>? parse$$spacing() {
List<int>? $0;
final $1 = _ch;
final $2 = _pos;
List<int>? $3;
final $4 = <int>[];
while (true) {
const $6 = [9, 10, 13, 13, 32, 32];
final $5 = _matchRange($6);
if (!ok) {
break;
}
$4.add($5!);
}
ok = true;
$3 = $4;
if (ok) {
$0 = $3;
} else {
_pos = $2;
_ch = $1;
}
return $0;
}
void _buildError() {
final names = <String>[];
final ends = <int>[];
var failEnd = 0;
for (var i = 0; i < _failures.length; i += 2) {
final name = _failures[i] as String;
var end = _failures[i + 1] as int;
if (end == -1) {
end = _failStart;
}
if (failEnd < end) {
failEnd = end;
}
names.add(name);
ends.add(end);
}
final temp = <String>[];
for (var i = 0; i < names.length; i++) {
if (ends[i] == failEnd) {
temp.add(names[i]);
}
}
final expected = temp.toSet().toList();
expected.sort();
final sink = StringBuffer();
if (_failStart == failEnd) {
if (failEnd < _source.length) {
sink.write('Unexpected character ');
final ch = _getChar(_failStart);
if (ch >= 32 && ch < 126) {
sink.write('\'');
sink.write(String.fromCharCode(ch));
sink.write('\'');
} else {
sink.write('(');
sink.write(ch);
sink.write(')');
}
} else {
sink.write('Unexpected end of input');
}
if (expected.isNotEmpty) {
sink.write(', expected: ');
sink.write(expected.join(', '));
}
} else {
sink.write('Unterminated ');
if (expected.isEmpty) {
sink.write('unknown token');
} else if (expected.length == 1) {
sink.write('token ');
sink.write(expected[0]);
} else {
sink.write('tokens ');
sink.write(expected.join(', '));
}
}
error = FormatException(sink.toString(), _source, _failStart);
}
void _fail(String name) {
if (_pos < _failStart) {
return;
}
if (_failStart < _pos) {
_failStart = _pos;
_failures = [];
}
_failures.add(name);
_failures.add(_failPos);
}
int _getChar(int pos) {
if (pos < _source.length) {
var ch = _source.codeUnitAt(pos);
if (ch >= 0xD800 && ch <= 0xDBFF) {
if (pos + 1 < _source.length) {
final ch2 = _source.codeUnitAt(pos + 1);
if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x10000;
} else {
throw FormatException('Unpaired high surrogate', _source, pos);
}
} else {
throw FormatException('The source has been exhausted', _source, pos);
}
} else {
if (ch >= 0xDC00 && ch <= 0xDFFF) {
throw FormatException(
'UTF-16 surrogate values are illegal in UTF-32', _source, pos);
}
}
return ch;
}
return _eof;
}
int? _matchAny() {
if (_ch == _eof) {
if (_failPos < _pos) {
_failPos = _pos;
}
ok = false;
return null;
}
final ch = _ch;
_pos += _ch <= 0xffff ? 1 : 2;
_ch = _getChar(_pos);
ok = true;
return ch;
}
T? _matchChar<T>(int ch, T? result) {
if (ch != _ch) {
if (_failPos < _pos) {
_failPos = _pos;
}
ok = false;
return null;
}
_pos += _ch <= 0xffff ? 1 : 2;
_ch = _getChar(_pos);
ok = true;
return result;
}
int? _matchRange(List<int> ranges) {
// Use binary search
for (var i = 0; i < ranges.length; i += 2) {
if (ranges[i] <= _ch) {
if (ranges[i + 1] >= _ch) {
final ch = _ch;
_pos += _ch <= 0xffff ? 1 : 2;
_ch = _getChar(_pos);
ok = true;
return ch;
}
} else {
break;
}
}
ok = false;
if (_failPos < _pos) {
_failPos = _pos;
}
return null;
}
String? _matchString(String text) {
var i = 0;
if (_ch == text.codeUnitAt(0)) {
i++;
if (_pos + text.length <= _source.length) {
for (; i < text.length; i++) {
if (text.codeUnitAt(i) != _source.codeUnitAt(_pos + i)) {
break;
}
}
}
}
ok = i == text.length;
if (ok) {
_pos = _pos + text.length;
_ch = _getChar(_pos);
return text;
} else {
final pos = _pos + i;
if (_failPos < pos) {
_failPos = pos;
}
return null;
}
}
void _reset() {
error = null;
_failPos = 0;
_failStart = 0;
_failures = [];
_pos = 0;
_ch = _getChar(0);
ok = false;
}
}
// ignore: unused_element