Publish angel3_combinator

This commit is contained in:
thomashii@dukefirehawk.com 2021-05-14 14:11:50 +08:00
parent b56724aab5
commit 33f51d837b
22 changed files with 105 additions and 92 deletions

View file

@ -1,44 +1,55 @@
# Created by .ignore support plugin (hsz.mobi)
### Dart template
# See https://www.dartlang.org/tools/private-files.html # See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub # Files and directories created by pub
.dart_tool
.packages .packages
.pub/ .pub/
build/ build/
# If you're building an application, you may want to check-in your pubspec.lock # If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock pubspec.lock
# Directory created by dartdoc # Directory created by dartdoc
# If you don't generate documentation locally you can remove this line. # If you don't generate documentation locally you can remove this line.
doc/api/ doc/api/
### Dart template
# See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub
# SDK 1.20 and later (no longer creates packages directories)
# Older SDK versions
# (Include if the minimum SDK version specified in pubsepc.yaml is earlier than 1.20)
.project
.buildlog
**/packages/
# Files created by dart2js
# (Most Dart developers will use pub build to compile Dart, use/modify these
# rules if you intend to use dart2js directly
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
# differentiate from explicit Javascript files)
*.dart.js
*.part.js
*.js.deps
*.js.map
*.info.json
# Directory created by dartdoc
# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
### JetBrains template ### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff: # User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files: ## VsCode
.idea/**/dataSources/ .vscode/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format: ## File-based project format:
*.iws *.iws
@ -46,21 +57,15 @@ cmake-build-debug/
## Plugin-specific files: ## Plugin-specific files:
# IntelliJ # IntelliJ
out/ .idea/
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/ .idea_modules/
# JIRA plugin # JIRA plugin
atlassian-ide-plugin.xml atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ) # Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml com_crashlytics_export_strings.xml
crashlytics.properties crashlytics.properties
crashlytics-build.properties crashlytics-build.properties
fabric.properties fabric.properties
.dart_tool

View file

@ -1,2 +1,12 @@
Tobe O <thosakwe@gmail.com> Primary Authors
Thomas Hii <thomashii@dukefirehawk.com> ===============
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
Thomas is the current maintainer of the code base. He has refactored and migrated the
code base to support NNBD.
* __[Tobe O](thosakwe@gmail.com)__
Tobe has written much of the original code prior to NNBD migration. He has moved on and
is no longer involved with the project.

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2017 Tobe O Copyright (c) 2021 dukefirehawk.com
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,6 +1,8 @@
# combinator # angel3_combinator
[![version](https://img.shields.io/pub/v/combinator.svg)](https://pub.dartlang.org/packages/combinator) [![version](https://img.shields.io/badge/pub-v2.12.4-brightgreen)](https://pub.dartlang.org/packages/angel3_combinator)
[![build status](https://travis-ci.org/thosakwe/combinator.svg)](https://travis-ci.org/thosakwe/combinator) [![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/combinator)
Packrat parser combinators that support static typing, generics, file spans, memoization, and more. Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
@ -16,7 +18,7 @@ The examples contain examples of using:
void main() { void main() {
// Parse a Pattern (usually String or RegExp). // Parse a Pattern (usually String or RegExp).
var foo = match('foo'); var foo = match('foo');
var number = match(new RegExp(r'[0-9]+'), errorMessage: 'Expected a number.'); var number = match(RegExp(r'[0-9]+'), errorMessage: 'Expected a number.');
// Set a value. // Set a value.
var numWithValue = number.map((r) => int.parse(r.span.text)); var numWithValue = number.map((r) => int.parse(r.span.text));
@ -64,7 +66,7 @@ void main() {
## Error Messages ## Error Messages
Parsers without descriptive error messages can lead to frustrating dead-ends Parsers without descriptive error messages can lead to frustrating dead-ends
for end-users. Fortunately, `combinator` is built with error handling in mind. for end-users. Fortunately, `angel3_combinator` is built with error handling in mind.
```dart ```dart
void main(Parser parser) { void main(Parser parser) {
@ -98,7 +100,7 @@ void main(Parser parser) {
``` ```
## For Programming Languages ## For Programming Languages
`combinator` was conceived to make writing parsers for complex grammars easier, `angel3_combinator` was conceived to make writing parsers for complex grammars easier,
namely programming languages. Thus, there are functions built-in to make common constructs namely programming languages. Thus, there are functions built-in to make common constructs
easier: easier:
@ -115,6 +117,6 @@ void main(Parser parser) {
``` ```
## Differences between this and Petitparser ## Differences between this and Petitparser
* `combinator` makes extensive use of Dart's dynamic typing * `angel3_combinator` makes extensive use of Dart's dynamic typing
* `combinator` supports detailed error messages (with configurable severity) * `angel3_combinator` supports detailed error messages (with configurable severity)
* `combinator` keeps track of locations (ex. `line 1: 3`) * `angel3_combinator` keeps track of locations (ex. `line 1: 3`)

View file

@ -2,14 +2,14 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
/// Parse a part of a decoded Basic auth string. /// Parse a part of a decoded Basic auth string.
/// ///
/// Namely, the `username` or `password` in `{username}:{password}`. /// Namely, the `username` or `password` in `{username}:{password}`.
final Parser<String> string = final Parser<String> string =
match<String>(new RegExp(r'[^:$]+'), errorMessage: 'Expected a string.') match<String>(RegExp(r'[^:$]+'), errorMessage: 'Expected a string.')
.value((r) => r.span!.text); .value((r) => r.span!.text);
/// Transforms `{username}:{password}` to `{"username": username, "password": password}`. /// Transforms `{username}:{password}` to `{"username": username, "password": password}`.
@ -25,11 +25,11 @@ final Parser<Map<String, String>> credentials = chain<String>([
/// This is used here to BASE64URL-decode a string, and then /// This is used here to BASE64URL-decode a string, and then
/// parse the decoded string. /// parse the decoded string.
final Parser credentialString = match<Map<String, String>?>( final Parser credentialString = match<Map<String, String>?>(
new RegExp(r'([^\n$]+)'), RegExp(r'([^\n$]+)'),
errorMessage: 'Expected a credential string.') errorMessage: 'Expected a credential string.')
.value((r) { .value((r) {
var decoded = utf8.decode(base64Url.decode(r.span!.text)); var decoded = utf8.decode(base64Url.decode(r.span!.text));
var scanner = new SpanScanner(decoded); var scanner = SpanScanner(decoded);
return credentials.parse(scanner).value; return credentials.parse(scanner).value;
}); });
@ -41,7 +41,7 @@ void main() {
while (true) { while (true) {
stdout.write('Enter a basic auth value: '); stdout.write('Enter a basic auth value: ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var scanner = new SpanScanner(line, sourceUrl: 'stdin'); var scanner = SpanScanner(line, sourceUrl: 'stdin');
var result = basicAuth.parse(scanner); var result = basicAuth.parse(scanner);
if (!result.successful) { if (!result.successful) {

View file

@ -1,19 +1,19 @@
import 'dart:math'; import 'dart:math';
import 'dart:io'; import 'dart:io';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
/// Note: This grammar does not handle precedence, for the sake of simplicity. /// Note: This grammar does not handle precedence, for the sake of simplicity.
Parser<num> calculatorGrammar() { Parser<num> calculatorGrammar() {
var expr = reference<num>(); var expr = reference<num>();
var number = match<num>(new RegExp(r'-?[0-9]+(\.[0-9]+)?')) var number = match<num>(RegExp(r'-?[0-9]+(\.[0-9]+)?'))
.value((r) => num.parse(r.span!.text)); .value((r) => num.parse(r.span!.text));
var hex = match<int>(new RegExp(r'0x([A-Fa-f0-9]+)')) var hex = match<int>(RegExp(r'0x([A-Fa-f0-9]+)'))
.map((r) => int.parse(r.scanner.lastMatch![1]!, radix: 16)); .map((r) => int.parse(r.scanner.lastMatch![1]!, radix: 16));
var binary = match<int>(new RegExp(r'([0-1]+)b')) var binary = match<int>(RegExp(r'([0-1]+)b'))
.map((r) => int.parse(r.scanner.lastMatch![1]!, radix: 2)); .map((r) => int.parse(r.scanner.lastMatch![1]!, radix: 2));
var alternatives = <Parser<num>>[]; var alternatives = <Parser<num>>[];
@ -56,7 +56,7 @@ void main() {
while (true) { while (true) {
stdout.write('Enter an expression: '); stdout.write('Enter an expression: ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var scanner = new SpanScanner(line, sourceUrl: 'stdin'); var scanner = SpanScanner(line, sourceUrl: 'stdin');
var result = calculator.parse(scanner); var result = calculator.parse(scanner);
if (!result.successful) { if (!result.successful) {

View file

@ -1,5 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
final Parser<String> id = final Parser<String> id =
@ -14,7 +14,7 @@ main() {
while (true) { while (true) {
stdout.write('Enter a string (ex "a,b,c"): '); stdout.write('Enter a string (ex "a,b,c"): ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var scanner = new SpanScanner(line, sourceUrl: 'stdin'); var scanner = SpanScanner(line, sourceUrl: 'stdin');
var result = id.separatedBy(match(',').space()).parse(scanner); var result = id.separatedBy(match(',').space()).parse(scanner);
if (!result.successful) { if (!result.successful) {

View file

@ -1,12 +1,12 @@
import 'dart:io'; import 'dart:io';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
Parser jsonGrammar() { Parser jsonGrammar() {
var expr = reference(); var expr = reference();
// Parse a number // Parse a number
var number = match<num>(new RegExp(r'-?[0-9]+(\.[0-9]+)?'), var number = match<num>(RegExp(r'-?[0-9]+(\.[0-9]+)?'),
errorMessage: 'Expected a number.') errorMessage: 'Expected a number.')
.value( .value(
(r) => num.parse(r.span!.text), (r) => num.parse(r.span!.text),
@ -14,7 +14,7 @@ Parser jsonGrammar() {
// Parse a string (no escapes supported, because lazy). // Parse a string (no escapes supported, because lazy).
var string = var string =
match(new RegExp(r'"[^"]*"'), errorMessage: 'Expected a string.').value( match(RegExp(r'"[^"]*"'), errorMessage: 'Expected a string.').value(
(r) => r.span!.text.substring(1, r.span!.text.length - 1), (r) => r.span!.text.substring(1, r.span!.text.length - 1),
); );
@ -56,7 +56,7 @@ main() {
while (true) { while (true) {
stdout.write('Enter some JSON: '); stdout.write('Enter some JSON: ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var scanner = new SpanScanner(line, sourceUrl: 'stdin'); var scanner = SpanScanner(line, sourceUrl: 'stdin');
var result = JSON.parse(scanner); var result = JSON.parse(scanner);
if (!result.successful) { if (!result.successful) {

View file

@ -1,11 +1,11 @@
import 'dart:io'; import 'dart:io';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
final Parser minus = match('-'); final Parser minus = match('-');
final Parser<int> digit = final Parser<int> digit =
match(new RegExp(r'[0-9]'), errorMessage: 'Expected a number'); match(RegExp(r'[0-9]'), errorMessage: 'Expected a number');
final Parser digits = digit.plus(); final Parser digits = digit.plus();
@ -23,7 +23,7 @@ main() {
while (true) { while (true) {
stdout.write('Enter a number: '); stdout.write('Enter a number: ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var scanner = new SpanScanner(line, sourceUrl: 'stdin'); var scanner = SpanScanner(line, sourceUrl: 'stdin');
var result = number.parse(scanner); var result = number.parse(scanner);
if (!result.successful) { if (!result.successful) {

View file

@ -1,7 +1,7 @@
// For some reason, this cannot be run in checked mode??? // For some reason, this cannot be run in checked mode???
import 'dart:io'; import 'dart:io';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
final Parser<String> key = final Parser<String> key =
@ -30,7 +30,7 @@ main() {
while (true) { while (true) {
stdout.write('Enter a query string: '); stdout.write('Enter a query string: ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var scanner = new SpanScanner(line, sourceUrl: 'stdin'); var scanner = SpanScanner(line, sourceUrl: 'stdin');
var result = pairs.parse(scanner); var result = pairs.parse(scanner);
if (!result.successful) { if (!result.successful) {

View file

@ -1,7 +1,7 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -10,7 +10,7 @@ void main() {
var symbols = <String, dynamic>{}; var symbols = <String, dynamic>{};
void registerFunction(String name, int nArgs, Function(List<num>) f) { void registerFunction(String name, int nArgs, Function(List<num>) f) {
symbols[name] = new Tuple2(nArgs, f); symbols[name] = Tuple2(nArgs, f);
} }
registerFunction('**', 2, (args) => pow(args[0], args[1])); registerFunction('**', 2, (args) => pow(args[0], args[1]));
@ -25,12 +25,12 @@ void main() {
return args[0]; return args[0];
}); });
var number = match(new RegExp(r'[0-9]+(\.[0-9]+)?'), var number =
errorMessage: 'Expected a number.') match(RegExp(r'[0-9]+(\.[0-9]+)?'), errorMessage: 'Expected a number.')
.map((r) => num.parse(r.span!.text)); .map((r) => num.parse(r.span!.text));
var id = match( var id = match(
new RegExp( RegExp(
r'[A-Za-z_!\\$",\\+-\\./:;\\?<>%&\\*@\[\]\\{\}\\|`\\^~][A-Za-z0-9_!\\$",\\+-\\./:;\\?<>%&\*@\[\]\\{\}\\|`\\^~]*'), r'[A-Za-z_!\\$",\\+-\\./:;\\?<>%&\\*@\[\]\\{\}\\|`\\^~][A-Za-z0-9_!\\$",\\+-\\./:;\\?<>%&\*@\[\]\\{\}\\|`\\^~]*'),
errorMessage: 'Expected an ID') errorMessage: 'Expected an ID')
.map((r) => symbols[r.span!.text] ??= .map((r) => symbols[r.span!.text] ??=
@ -41,7 +41,7 @@ void main() {
var list = expr.space().times(2, exact: false).map((r) { var list = expr.space().times(2, exact: false).map((r) {
try { try {
var out = []; var out = [];
var q = new Queue.from(r.value!.reversed); var q = Queue.from(r.value!.reversed);
while (q.isNotEmpty) { while (q.isNotEmpty) {
var current = q.removeFirst(); var current = q.removeFirst();
@ -70,7 +70,7 @@ void main() {
while (true) { while (true) {
stdout.write('> '); stdout.write('> ');
var line = stdin.readLineSync()!; var line = stdin.readLineSync()!;
var result = expr.parse(new SpanScanner(line)); var result = expr.parse(SpanScanner(line));
if (result.errors.isNotEmpty) { if (result.errors.isNotEmpty) {
for (var error in result.errors) { for (var error in result.errors) {

View file

@ -1,4 +1,4 @@
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
void main() { void main() {

View file

@ -2,7 +2,7 @@ library lex.src.combinator;
import 'dart:collection'; import 'dart:collection';
import 'package:code_buffer/code_buffer.dart'; import 'package:angel3_code_buffer/angel3_code_buffer.dart';
import 'package:matcher/matcher.dart'; import 'package:matcher/matcher.dart';
import 'package:source_span/source_span.dart'; import 'package:source_span/source_span.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';

View file

@ -1,16 +1,12 @@
name: combinator name: angel3_combinator
version: 2.0.0-beta.1 version: 2.0.0
description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more. description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
homepage: https://github.com/dukefirehawk/angel/tree/sdk-2.12.x_nnbd/packages/combinator homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/combinator
publish_to: none publish_to: none
environment: environment:
sdk: '>=2.12.0 <3.0.0' sdk: '>=2.12.0 <3.0.0'
dependencies: dependencies:
code_buffer: angel3_code_buffer: ^2.0.0
git:
url: https://github.com/dukefirehawk/angel.git
ref: sdk-2.12.x_nnbd
path: packages/code_buffer
matcher: ^0.12.0 matcher: ^0.12.0
source_span: ^1.8.1 source_span: ^1.8.1
string_scanner: ^1.1.0 string_scanner: ^1.1.0

View file

@ -4,7 +4,7 @@ import 'match_test.dart' as match;
import 'misc_test.dart' as misc; import 'misc_test.dart' as misc;
import 'value_test.dart' as value; import 'value_test.dart' as value;
main() { void main() {
group('list', list.main); group('list', list.main);
group('match', match.main); group('match', match.main);
group('value', value.main); group('value', value.main);

View file

@ -1,4 +1,4 @@
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'common.dart'; import 'common.dart';

View file

@ -1,8 +1,8 @@
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'common.dart'; import 'common.dart';
main() { void main() {
test('match string', () { test('match string', () {
expect(match('hello').parse(scan('hello world')).successful, isTrue); expect(match('hello').parse(scan('hello world')).successful, isTrue);
}); });

View file

@ -1,9 +1,9 @@
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:matcher/matcher.dart'; import 'package:matcher/matcher.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'common.dart'; import 'common.dart';
main() { void main() {
test('advance', () { test('advance', () {
var scanner = scan('hello world'); var scanner = scan('hello world');

View file

@ -1,4 +1,4 @@
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:string_scanner/string_scanner.dart'; import 'package:string_scanner/string_scanner.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';

View file

@ -1,8 +1,8 @@
import 'package:combinator/combinator.dart'; import 'package:angel3_combinator/angel3_combinator.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'common.dart'; import 'common.dart';
main() { void main() {
var parser = match('hello').value((r) => 'world'); var parser = match('hello').value((r) => 'world');
test('sets value', () { test('sets value', () {

View file

@ -1,4 +1,4 @@
# http_exception # angel3_http_exception
[![version](https://img.shields.io/badge/pub-v2.12.4-brightgreen)](https://pub.dartlang.org/packages/angel3_http_exception) [![version](https://img.shields.io/badge/pub-v2.12.4-brightgreen)](https://pub.dartlang.org/packages/angel3_http_exception)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) [![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)