diff --git a/CHANGELOG.md b/CHANGELOG.md index 56d989ba..58a0be02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## 4.2.0 + +* Refactored the framework internal to use [Belatuk Common Utilities]() +* Updated [examples] () +* Updated to use `lints` linter + +## 4.1.0 + +* Updated [website] () +* Updated [examples] () +* Fixed ORM code generator +* Fixed Serializer code generator +* Fixed graphQL code generator +* Fixed CLI +* Fixed failed test cases + ## 4.0.0 (NNBD) * Published all packages with `angel3_` prefix diff --git a/packages/code_buffer/.gitignore b/packages/code_buffer/.gitignore deleted file mode 100644 index 24d68312..00000000 --- a/packages/code_buffer/.gitignore +++ /dev/null @@ -1,71 +0,0 @@ -# See https://www.dartlang.org/tools/private-files.html - -# Files and directories created by pub -.dart_tool -.packages -.pub/ -build/ - -# If you're building an application, you may want to check-in your pubspec.lock -pubspec.lock - -# Directory created by dartdoc -# If you don't generate documentation locally you can remove this line. -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 -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: - -## VsCode -.vscode/ - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -.idea/ -/out/ -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties diff --git a/packages/code_buffer/.travis.yml b/packages/code_buffer/.travis.yml deleted file mode 100644 index de2210c9..00000000 --- a/packages/code_buffer/.travis.yml +++ /dev/null @@ -1 +0,0 @@ -language: dart \ No newline at end of file diff --git a/packages/code_buffer/AUTHORS.md b/packages/code_buffer/AUTHORS.md deleted file mode 100644 index ac95ab58..00000000 --- a/packages/code_buffer/AUTHORS.md +++ /dev/null @@ -1,12 +0,0 @@ -Primary Authors -=============== - -* __[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. diff --git a/packages/code_buffer/CHANGELOG.md b/packages/code_buffer/CHANGELOG.md deleted file mode 100644 index 468aa9a1..00000000 --- a/packages/code_buffer/CHANGELOG.md +++ /dev/null @@ -1,11 +0,0 @@ -# 2.0.3 -* Resolved static analysis warnings - -# 2.0.2 -* Updated README -# 2.0.1 -* Fixed invalid homepage url in pubspec.yaml -# 2.0.0 -* Migrated to support Dart SDK 2.12.x NNBD -# 1.0.1 -* Added `CodeBuffer.noWhitespace()`. \ No newline at end of file diff --git a/packages/code_buffer/LICENSE b/packages/code_buffer/LICENSE deleted file mode 100644 index 8f65b579..00000000 --- a/packages/code_buffer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License (MIT) - -Copyright (c) 2021 dukefirehawk.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/packages/code_buffer/README.md b/packages/code_buffer/README.md deleted file mode 100644 index b9371bb5..00000000 --- a/packages/code_buffer/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# angel3_code_buffer -[![version](https://img.shields.io/badge/pub-v2.0.3-brightgreen)](https://pub.dartlang.org/packages/angel3_code_buffer) -[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) -[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) - -[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/code_buffer/LICENSE) - -An advanced StringBuffer geared toward generating code, and source maps. - -# Installation -In your `pubspec.yaml`: - -```yaml -dependencies: - angel3_code_buffer: ^2.0.0 -``` - -# Usage -Use a `CodeBuffer` just like any regular `StringBuffer`: - -```dart -String someFunc() { - var buf = CodeBuffer(); - buf - ..write('hello ') - ..writeln('world!'); - return buf.toString(); -} -``` - -However, a `CodeBuffer` supports indentation. - -```dart -void someOtherFunc() { - var buf = CodeBuffer(); - // Custom options... - var buf = CodeBuffer(newline: '\r\n', space: '\t', trailingNewline: true); - - // Any following lines will have an incremented indentation level... - buf.indent(); - - // And vice-versa: - buf.outdent(); -} -``` - -`CodeBuffer` instances keep track of every `SourceSpan` they create. -This makes them useful for codegen tools, or to-JS compilers. - -```dart -void someFunc(CodeBuffer buf) { - buf.write('hello'); - expect(buf.lastLine.text, 'hello'); - - buf.writeln('world'); - expect(buf.lastLine.lastSpan.start.column, 5); -} -``` - -You can copy a `CodeBuffer` into another, heeding indentation rules: - -```dart -void yetAnotherFunc(CodeBuffer a, CodeBuffer b) { - b.copyInto(a); -} -``` \ No newline at end of file diff --git a/packages/code_buffer/analysis_options.yaml b/packages/code_buffer/analysis_options.yaml deleted file mode 100644 index c230cee7..00000000 --- a/packages/code_buffer/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:pedantic/analysis_options.yaml -analyzer: - strong-mode: - implicit-casts: false \ No newline at end of file diff --git a/packages/code_buffer/example/main.dart b/packages/code_buffer/example/main.dart deleted file mode 100644 index 7d4463aa..00000000 --- a/packages/code_buffer/example/main.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:angel3_code_buffer/angel3_code_buffer.dart'; -import 'package:test/test.dart'; - -/// Use a `CodeBuffer` just like any regular `StringBuffer`: -String someFunc() { - var buf = CodeBuffer(); - buf - ..write('hello ') - ..writeln('world!'); - return buf.toString(); -} - -/// However, a `CodeBuffer` supports indentation. -void someOtherFunc() { - var buf = CodeBuffer(); - - // Custom options... - // ignore: unused_local_variable - var customBuf = - CodeBuffer(newline: '\r\n', space: '\t', trailingNewline: true); - - // Without whitespace.. - // ignore: unused_local_variable - var minifyingBuf = CodeBuffer.noWhitespace(); - - // Any following lines will have an incremented indentation level... - buf.indent(); - - // And vice-versa: - buf.outdent(); -} - -/// `CodeBuffer` instances keep track of every `SourceSpan` they create. -//This makes them useful for codegen tools, or to-JS compilers. -void yetAnotherOtherFunc(CodeBuffer buf) { - buf.write('hello'); - expect(buf.lastLine!.text, 'hello'); - - buf.writeln('world'); - expect(buf.lastLine!.lastSpan!.start.column, 5); -} - -/// You can copy a `CodeBuffer` into another, heeding indentation rules: -void yetEvenAnotherFunc(CodeBuffer a, CodeBuffer b) { - b.copyInto(a); -} diff --git a/packages/code_buffer/lib/angel3_code_buffer.dart b/packages/code_buffer/lib/angel3_code_buffer.dart deleted file mode 100644 index 4fd9bea6..00000000 --- a/packages/code_buffer/lib/angel3_code_buffer.dart +++ /dev/null @@ -1,231 +0,0 @@ -import 'package:source_span/source_span.dart'; - -/// An advanced StringBuffer geared toward generating code, and source maps. -class CodeBuffer implements StringBuffer { - /// The character sequence used to represent a line break. - final String newline; - - /// The character sequence used to represent a space/tab. - final String space; - - /// The source URL to be applied to all generated [SourceSpan] instances. - final sourceUrl; - - /// If `true` (default: `false`), then an additional [newline] will be inserted at the end of the generated string. - final bool trailingNewline; - - final List _lines = []; - CodeBufferLine? _currentLine, _lastLine; - int _indentationLevel = 0; - int _length = 0; - - CodeBuffer( - {this.space = ' ', - this.newline = '\n', - this.trailingNewline = false, - this.sourceUrl}); - - /// Creates a [CodeBuffer] that does not emit additional whitespace. - factory CodeBuffer.noWhitespace({sourceUrl}) => CodeBuffer( - space: '', newline: '', trailingNewline: false, sourceUrl: sourceUrl); - - /// The last line created within this buffer. - CodeBufferLine? get lastLine => _lastLine; - - /// Returns an immutable collection of the [CodeBufferLine]s within this instance. - List get lines => List.unmodifiable(_lines); - - @override - bool get isEmpty => _lines.isEmpty; - - @override - bool get isNotEmpty => _lines.isNotEmpty; - - @override - int get length => _length; - - CodeBufferLine _createLine() { - var start = SourceLocation( - _length, - sourceUrl: sourceUrl, - line: _lines.length, - column: _indentationLevel * space.length, - ); - var line = CodeBufferLine._(_indentationLevel, start).._end = start; - _lines.add(_lastLine = line); - return line; - } - - /// Increments the indentation level. - void indent() { - _indentationLevel++; - } - - /// Decrements the indentation level, if it is greater than `0`. - void outdent() { - if (_indentationLevel > 0) _indentationLevel--; - } - - /// Copies the contents of this [CodeBuffer] into another, preserving indentation and source mapping information. - void copyInto(CodeBuffer other) { - if (_lines.isEmpty) return; - var i = 0; - - for (var line in _lines) { - // To compute offset: - // 1. Find current length of other - // 2. Add length of its newline - // 3. Add indentation - var column = (other._indentationLevel + line.indentationLevel) * - other.space.length; - var offset = other._length + other.newline.length + column; - - // Re-compute start + end - var start = SourceLocation( - offset, - sourceUrl: other.sourceUrl, - line: other._lines.length + i, - column: column, - ); - - var end = SourceLocation( - offset + line.span.length, - sourceUrl: other.sourceUrl, - line: start.line, - column: column + line._buf.length, - ); - - var clone = CodeBufferLine._( - line.indentationLevel + other._indentationLevel, start) - .._end = end - .._buf.write(line._buf.toString()); - - // Adjust lastSpan - if (line._lastSpan != null) { - var s = line._lastSpan!.start; - var lastSpanColumn = - ((line.indentationLevel + other._indentationLevel) * - other.space.length) + - line.text.indexOf(line._lastSpan!.text); - clone._lastSpan = SourceSpan( - SourceLocation( - offset + s.offset, - sourceUrl: other.sourceUrl, - line: clone.span.start.line, - column: lastSpanColumn, - ), - SourceLocation( - offset + s.offset + line._lastSpan!.length, - sourceUrl: other.sourceUrl, - line: clone.span.end.line, - column: lastSpanColumn + line._lastSpan!.length, - ), - line._lastSpan!.text, - ); - } - - other._lines.add(other._currentLine = other._lastLine = clone); - - // Adjust length accordingly... - other._length = offset + clone.span.length; - i++; - } - - other.writeln(); - } - - @override - void clear() { - _lines.clear(); - _length = _indentationLevel = 0; - _currentLine = null; - } - - @override - void writeCharCode(int charCode) { - _currentLine ??= _createLine(); - - _currentLine!._buf.writeCharCode(charCode); - var end = _currentLine!._end; - _currentLine!._end = SourceLocation( - end.offset + 1, - sourceUrl: end.sourceUrl, - line: end.line, - column: end.column + 1, - ); - _length++; - _currentLine!._lastSpan = - SourceSpan(end, _currentLine!._end, String.fromCharCode(charCode)); - } - - @override - void write(Object? obj) { - var msg = obj.toString(); - _currentLine ??= _createLine(); - _currentLine!._buf.write(msg); - var end = _currentLine!._end; - _currentLine!._end = SourceLocation( - end.offset + msg.length, - sourceUrl: end.sourceUrl, - line: end.line, - column: end.column + msg.length, - ); - _length += msg.length; - _currentLine!._lastSpan = SourceSpan(end, _currentLine!._end, msg); - } - - @override - void writeln([Object? obj = '']) { - if (obj != null && obj != '') write(obj); - _currentLine = null; - _length++; - } - - @override - void writeAll(Iterable objects, [String separator = '']) { - write(objects.join(separator)); - } - - @override - String toString() { - var buf = StringBuffer(); - var i = 0; - - for (var line in lines) { - if (i++ > 0) buf.write(newline); - for (var j = 0; j < line.indentationLevel; j++) { - buf.write(space); - } - buf.write(line._buf.toString()); - } - - if (trailingNewline == true) buf.write(newline); - - return buf.toString(); - } -} - -/// Represents a line of text within a [CodeBuffer]. -class CodeBufferLine { - /// Mappings from one [SourceSpan] to another, to aid with generating dynamic source maps. - final Map sourceMappings = {}; - - /// The level of indentation preceding this line. - final int indentationLevel; - - final SourceLocation _start; - final StringBuffer _buf = StringBuffer(); - late SourceLocation _end; - SourceSpan? _lastSpan; - - CodeBufferLine._(this.indentationLevel, this._start); - - /// The [SourceSpan] corresponding to the last text written to this line. - SourceSpan? get lastSpan => _lastSpan; - - /// The [SourceSpan] corresponding to this entire line. - SourceSpan get span => SourceSpan(_start, _end, _buf.toString()); - - /// The text within this line. - String get text => _buf.toString(); -} diff --git a/packages/code_buffer/pubspec.yaml b/packages/code_buffer/pubspec.yaml deleted file mode 100644 index afef3105..00000000 --- a/packages/code_buffer/pubspec.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: angel3_code_buffer -version: 2.0.3 -description: An advanced StringBuffer geared toward generating code, and source maps. -homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/code_buffer -environment: - sdk: '>=2.12.0 <3.0.0' -dependencies: - charcode: ^1.2.0 - source_span: ^1.8.1 -dev_dependencies: - test: ^1.17.3 - pedantic: ^1.11.0 diff --git a/packages/code_buffer/test/copy_test.dart b/packages/code_buffer/test/copy_test.dart deleted file mode 100644 index 01f60420..00000000 --- a/packages/code_buffer/test/copy_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:angel3_code_buffer/angel3_code_buffer.dart'; -import 'package:test/test.dart'; - -void main() { - var a = CodeBuffer(), b = CodeBuffer(); - - setUp(() { - a.writeln('outer block 1'); - b..writeln('inner block 1')..writeln('inner block 2'); - b.copyInto(a..indent()); - a - ..outdent() - ..writeln('outer block 2'); - }); - - tearDown(() { - a.clear(); - b.clear(); - }); - - test('sets correct text', () { - expect( - a.toString(), - [ - 'outer block 1', - ' inner block 1', - ' inner block 2', - 'outer block 2', - ].join('\n')); - }); - - test('sets lastLine+lastSpan', () { - var c = CodeBuffer() - ..indent() - ..write('>') - ..writeln('innermost'); - c.copyInto(a); - expect(a.lastLine!.text, '>innermost'); - expect(a.lastLine!.span.start.column, 2); - expect(a.lastLine!.lastSpan!.start.line, 4); - expect(a.lastLine!.lastSpan!.start.column, 3); - expect(a.lastLine!.lastSpan!.end.line, 4); - expect(a.lastLine!.lastSpan!.end.column, 12); - }); -} diff --git a/packages/code_buffer/test/span_test.dart b/packages/code_buffer/test/span_test.dart deleted file mode 100644 index 61615ae8..00000000 --- a/packages/code_buffer/test/span_test.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:charcode/charcode.dart'; -import 'package:angel3_code_buffer/angel3_code_buffer.dart'; -import 'package:test/test.dart'; - -void main() { - var buf = CodeBuffer(); - tearDown(buf.clear); - - test('writeCharCode', () { - buf.writeCharCode($x); - expect(buf.lastLine!.lastSpan!.start.column, 0); - expect(buf.lastLine!.lastSpan!.start.line, 0); - expect(buf.lastLine!.lastSpan!.end.column, 1); - expect(buf.lastLine!.lastSpan!.end.line, 0); - }); - - test('write', () { - buf.write('foo'); - expect(buf.lastLine!.lastSpan!.start.column, 0); - expect(buf.lastLine!.lastSpan!.start.line, 0); - expect(buf.lastLine!.lastSpan!.end.column, 3); - expect(buf.lastLine!.lastSpan!.end.line, 0); - }); - - test('multiple writes in one line', () { - buf..write('foo')..write('baz'); - expect(buf.lastLine!.lastSpan!.start.column, 3); - expect(buf.lastLine!.lastSpan!.start.line, 0); - expect(buf.lastLine!.lastSpan!.end.column, 6); - expect(buf.lastLine!.lastSpan!.end.line, 0); - }); - - test('multiple lines', () { - buf - ..writeln('foo') - ..write('bar') - ..write('+') - ..writeln('baz'); - expect(buf.lastLine!.lastSpan!.start.column, 4); - expect(buf.lastLine!.lastSpan!.start.line, 1); - expect(buf.lastLine!.lastSpan!.end.column, 7); - expect(buf.lastLine!.lastSpan!.end.line, 1); - }); -} diff --git a/packages/code_buffer/test/write_test.dart b/packages/code_buffer/test/write_test.dart deleted file mode 100644 index b8b3ca9a..00000000 --- a/packages/code_buffer/test/write_test.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'package:charcode/charcode.dart'; -import 'package:test/test.dart'; -import 'package:angel3_code_buffer/angel3_code_buffer.dart'; - -void main() { - var buf = CodeBuffer(); - tearDown(buf.clear); - - test('writeCharCode', () { - buf.writeCharCode($x); - expect(buf.toString(), 'x'); - }); - - test('write', () { - buf.write('hello world'); - expect(buf.toString(), 'hello world'); - }); - - test('custom space', () { - var b = CodeBuffer(space: '+') - ..writeln('foo') - ..indent() - ..writeln('baz'); - expect(b.toString(), 'foo\n+baz'); - }); - - test('custom newline', () { - var b = CodeBuffer(newline: 'N') - ..writeln('foo') - ..indent() - ..writeln('baz'); - expect(b.toString(), 'fooN baz'); - }); - - test('trailing newline', () { - var b = CodeBuffer(trailingNewline: true)..writeln('foo'); - expect(b.toString(), 'foo\n'); - }); - - group('multiple lines', () { - setUp(() { - buf..writeln('foo')..writeln('bar')..writeln('baz'); - expect(buf.lines, hasLength(3)); - expect(buf.lines[0].text, 'foo'); - expect(buf.lines[1].text, 'bar'); - expect(buf.lines[2].text, 'baz'); - }); - }); - - test('indent', () { - buf - ..writeln('foo') - ..indent() - ..writeln('bar') - ..indent() - ..writeln('baz') - ..outdent() - ..writeln('quux') - ..outdent() - ..writeln('end'); - expect(buf.toString(), 'foo\n bar\n baz\n quux\nend'); - }); - - group('sets lastLine text', () { - test('writeCharCode', () { - buf.writeCharCode($x); - expect(buf.lastLine!.text, 'x'); - }); - - test('write', () { - buf.write('hello world'); - expect(buf.lastLine!.text, 'hello world'); - }); - }); - - group('sets lastLine lastSpan', () { - test('writeCharCode', () { - buf.writeCharCode($x); - expect(buf.lastLine!.lastSpan!.text, 'x'); - }); - - test('write', () { - buf.write('hello world'); - expect(buf.lastLine!.lastSpan!.text, 'hello world'); - }); - }); -} diff --git a/packages/combinator/.gitignore b/packages/combinator/.gitignore deleted file mode 100644 index 24d68312..00000000 --- a/packages/combinator/.gitignore +++ /dev/null @@ -1,71 +0,0 @@ -# See https://www.dartlang.org/tools/private-files.html - -# Files and directories created by pub -.dart_tool -.packages -.pub/ -build/ - -# If you're building an application, you may want to check-in your pubspec.lock -pubspec.lock - -# Directory created by dartdoc -# If you don't generate documentation locally you can remove this line. -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 -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: - -## VsCode -.vscode/ - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -.idea/ -/out/ -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties diff --git a/packages/combinator/.travis.yml b/packages/combinator/.travis.yml deleted file mode 100644 index 2f22c5ce..00000000 --- a/packages/combinator/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: dart -dart: - - stable - - dev \ No newline at end of file diff --git a/packages/combinator/AUTHORS.md b/packages/combinator/AUTHORS.md deleted file mode 100644 index ac95ab58..00000000 --- a/packages/combinator/AUTHORS.md +++ /dev/null @@ -1,12 +0,0 @@ -Primary Authors -=============== - -* __[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. diff --git a/packages/combinator/CHANGELOG.md b/packages/combinator/CHANGELOG.md deleted file mode 100644 index cea07a47..00000000 --- a/packages/combinator/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# 2.0.2 -* Resolve static analysis warnings - -# 2.0.1 -* Updated README - -# 2.0.0 -* Migrated to support Dart SDK 2.12.x NNBD - -# 1.1.0 -* Add `tupleX` parsers. Hooray for strong typing! - -# 1.0.0+3 -* `then` now *always* returns `dynamic`. - -# 1.0.0+2 -* `star` now includes with a call to `opt`. -* Added comments. -* Enforce generics on `separatedBy`. -* Enforce Dart 2 semantics. \ No newline at end of file diff --git a/packages/combinator/LICENSE b/packages/combinator/LICENSE deleted file mode 100644 index 8f65b579..00000000 --- a/packages/combinator/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License (MIT) - -Copyright (c) 2021 dukefirehawk.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/packages/combinator/README.md b/packages/combinator/README.md deleted file mode 100644 index 0c0e509e..00000000 --- a/packages/combinator/README.md +++ /dev/null @@ -1,123 +0,0 @@ -# angel3_combinator -[![version](https://img.shields.io/badge/pub-v2.0.2-brightgreen)](https://pub.dartlang.org/packages/angel3_combinator) -[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) -[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) - -[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/combinator/LICENSE) - -Packrat parser combinators that support static typing, generics, file spans, memoization, and more. - -**RECOMMENDED:** -Check `example/` for examples. -The examples contain examples of using: -* Generic typing -* Reading `FileSpan` from `ParseResult` -* More... - -## Basic Usage -```dart -void main() { - // Parse a Pattern (usually String or RegExp). - var foo = match('foo'); - var number = match(RegExp(r'[0-9]+'), errorMessage: 'Expected a number.'); - - // Set a value. - var numWithValue = number.map((r) => int.parse(r.span.text)); - - // Expect a pattern, or nothing. - var optional = numWithValue.opt(); - - // Expect a pattern zero or more times. - var star = optional.star(); - - // Expect one or more times. - var plus = optional.plus(); - - // Expect an arbitrary number of times. - var threeTimes = optional.times(3); - - // Expect a sequence of patterns. - var doraTheExplorer = chain([ - match('Dora').space(), - match('the').space(), - match('Explorer').space(), - ]); - - // Choose exactly one of a set of patterns, whichever - // appears first. - var alt = any([ - match('1'), - match('11'), - match('111'), - ]); - - // Choose the *longest* match for any of the given alternatives. - var alt2 = longest([ - match('1'), - match('11'), - match('111'), - ]); - - // Friendly operators - var fooOrNumber = foo | number; - var fooAndNumber = foo & number; - var notFoo = ~foo; -} -``` - -## Error Messages -Parsers without descriptive error messages can lead to frustrating dead-ends -for end-users. Fortunately, `angel3_combinator` is built with error handling in mind. - -```dart -void main(Parser parser) { - // Append an arbitrary error message to a parser if it is not matched. - var withError = parser.error(errorMessage: 'Hey!!! Wrong!!!'); - - // You can also set the severity of an error. - var asHint = parser.error(severity: SyntaxErrorSeverity.hint); - - // Constructs like `any`, `chain`, and `longest` support this as well. - var foo = longest([ - parser.error(errorMessage: 'foo'), - parser.error(errorMessage: 'bar') - ], errorMessage: 'Expected a "foo" or a "bar"'); - - // If multiple errors are present at one location, - // it can create a lot of noise. - // - // Use `foldErrors` to only take one error at a given location. - var lessNoise = parser.foldErrors(); -} -``` - -## Whitespaces -Handling optional whitespace is dead-easy: - -```dart -void main(Parser parser) { - var optionalSpace = parser.space(); -} -``` - -## For Programming Languages -`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 -easier: - -```dart -void main(Parser parser) { - var array = parser - .separatedByComma() - .surroundedBySquareBrackets(defaultValue: []); - - var braces = parser.surroundedByCurlyBraces(); - - var sep = parser.separatedBy(match('!').space()); -} -``` - -## Differences between this and Petitparser -* `angel3_combinator` makes extensive use of Dart's dynamic typing -* `angel3_combinator` supports detailed error messages (with configurable severity) -* `angel3_combinator` keeps track of locations (ex. `line 1: 3`) \ No newline at end of file diff --git a/packages/combinator/analysis_options.yaml b/packages/combinator/analysis_options.yaml deleted file mode 100644 index 8dc465d4..00000000 --- a/packages/combinator/analysis_options.yaml +++ /dev/null @@ -1,5 +0,0 @@ -include: package:pedantic/analysis_options.yaml -analyzer: - strong-mode: - implicit-casts: false - #implicit-dynamic: false \ No newline at end of file diff --git a/packages/combinator/combinator.iml b/packages/combinator/combinator.iml deleted file mode 100644 index 75734c90..00000000 --- a/packages/combinator/combinator.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/combinator/example/basic_auth.dart b/packages/combinator/example/basic_auth.dart deleted file mode 100644 index 623be5c7..00000000 --- a/packages/combinator/example/basic_auth.dart +++ /dev/null @@ -1,56 +0,0 @@ -// Run this with "Basic QWxhZGRpbjpPcGVuU2VzYW1l" - -import 'dart:convert'; -import 'dart:io'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -/// Parse a part of a decoded Basic auth string. -/// -/// Namely, the `username` or `password` in `{username}:{password}`. -final Parser string = - match(RegExp(r'[^:$]+'), errorMessage: 'Expected a string.') - .value((r) => r.span!.text); - -/// Transforms `{username}:{password}` to `{"username": username, "password": password}`. -final Parser> credentials = chain([ - string.opt(), - match(':'), - string.opt(), -]).map>( - (r) => {'username': r.value![0], 'password': r.value![2]}); - -/// We can actually embed a parser within another parser. -/// -/// This is used here to BASE64URL-decode a string, and then -/// parse the decoded string. -final Parser credentialString = match?>( - RegExp(r'([^\n$]+)'), - errorMessage: 'Expected a credential string.') - .value((r) { - var decoded = utf8.decode(base64Url.decode(r.span!.text)); - var scanner = SpanScanner(decoded); - return credentials.parse(scanner).value; -}); - -final Parser basic = match('Basic').space(); - -final Parser basicAuth = basic.then(credentialString).index(1); - -void main() { - while (true) { - stdout.write('Enter a basic auth value: '); - var line = stdin.readLineSync()!; - var scanner = SpanScanner(line, sourceUrl: 'stdin'); - var result = basicAuth.parse(scanner); - - if (!result.successful) { - for (var error in result.errors) { - print(error.toolString); - print(error.span!.highlight(color: true)); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/calculator.dart b/packages/combinator/example/calculator.dart deleted file mode 100644 index 552bc744..00000000 --- a/packages/combinator/example/calculator.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'dart:math'; -import 'dart:io'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -/// Note: This grammar does not handle precedence, for the sake of simplicity. -Parser calculatorGrammar() { - var expr = reference(); - - var number = match(RegExp(r'-?[0-9]+(\.[0-9]+)?')) - .value((r) => num.parse(r.span!.text)); - - var hex = match(RegExp(r'0x([A-Fa-f0-9]+)')) - .map((r) => int.parse(r.scanner.lastMatch![1]!, radix: 16)); - - var binary = match(RegExp(r'([0-1]+)b')) - .map((r) => int.parse(r.scanner.lastMatch![1]!, radix: 2)); - - var alternatives = >[]; - - void registerBinary(String op, num Function(num, num) f) { - alternatives.add( - chain([ - expr.space(), - match(op).space() as Parser, - expr.space(), - ]).map((r) => f(r.value![0], r.value![2])), - ); - } - - registerBinary('**', (a, b) => pow(a, b)); - registerBinary('*', (a, b) => a * b); - registerBinary('/', (a, b) => a / b); - registerBinary('%', (a, b) => a % b); - registerBinary('+', (a, b) => a + b); - registerBinary('-', (a, b) => a - b); - registerBinary('^', (a, b) => a.toInt() ^ b.toInt()); - registerBinary('&', (a, b) => a.toInt() & b.toInt()); - registerBinary('|', (a, b) => a.toInt() | b.toInt()); - - alternatives.addAll([ - number, - hex, - binary, - expr.parenthesized(), - ]); - - expr.parser = longest(alternatives); - - return expr; -} - -void main() { - var calculator = calculatorGrammar(); - - while (true) { - stdout.write('Enter an expression: '); - var line = stdin.readLineSync()!; - var scanner = SpanScanner(line, sourceUrl: 'stdin'); - var result = calculator.parse(scanner); - - if (!result.successful) { - for (var error in result.errors) { - stderr.writeln(error.toolString); - stderr.writeln(error.span!.highlight(color: true)); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/delimiter.dart b/packages/combinator/example/delimiter.dart deleted file mode 100644 index 4571790c..00000000 --- a/packages/combinator/example/delimiter.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'dart:io'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -final Parser id = - match(RegExp(r'[A-Za-z]+')).value((r) => r.span!.text); - -// We can use `separatedBy` to easily construct parser -// that can be matched multiple times, separated by another -// pattern. -// -// This is useful for parsing arrays or map literals. -void main() { - while (true) { - stdout.write('Enter a string (ex "a,b,c"): '); - var line = stdin.readLineSync()!; - var scanner = SpanScanner(line, sourceUrl: 'stdin'); - var result = id.separatedBy(match(',').space()).parse(scanner); - - if (!result.successful) { - for (var error in result.errors) { - print(error.toolString); - print(error.span!.highlight(color: true)); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/json.dart b/packages/combinator/example/json.dart deleted file mode 100644 index caaba890..00000000 --- a/packages/combinator/example/json.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'dart:io'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -Parser jsonGrammar() { - var expr = reference(); - - // Parse a number - var number = match(RegExp(r'-?[0-9]+(\.[0-9]+)?'), - errorMessage: 'Expected a number.') - .value( - (r) => num.parse(r.span!.text), - ); - - // Parse a string (no escapes supported, because lazy). - var string = - match(RegExp(r'"[^"]*"'), errorMessage: 'Expected a string.').value( - (r) => r.span!.text.substring(1, r.span!.text.length - 1), - ); - - // Parse an array - var array = expr - .space() - .separatedByComma() - .surroundedBySquareBrackets(defaultValue: []); - - // KV pair - var keyValuePair = chain([ - string.space(), - match(':').space(), - expr.error(errorMessage: 'Missing expression.'), - ]).castDynamic().cast().value((r) => {r.value![0]: r.value![2]}); - - // Parse an object. - var object = keyValuePair - .separatedByComma() - .castDynamic() - .surroundedByCurlyBraces(defaultValue: {}); - - expr.parser = longest( - [ - array, - number, - string, - object.error(), - ], - errorMessage: 'Expected an expression.', - ).space(); - - return expr.foldErrors(); -} - -void main() { - var JSON = jsonGrammar(); - - while (true) { - stdout.write('Enter some JSON: '); - var line = stdin.readLineSync()!; - var scanner = SpanScanner(line, sourceUrl: 'stdin'); - var result = JSON.parse(scanner); - - if (!result.successful) { - for (var error in result.errors) { - print(error.toolString); - print(error.span!.highlight(color: true)); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/main.dart b/packages/combinator/example/main.dart deleted file mode 100644 index 1ea328c6..00000000 --- a/packages/combinator/example/main.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'dart:io'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -final Parser minus = match('-'); - -final Parser digit = - match(RegExp(r'[0-9]'), errorMessage: 'Expected a number'); - -final Parser digits = digit.plus(); - -final Parser dot = match('.'); - -final Parser decimal = ( // digits, (dot, digits)? - digits & (dot & digits).opt() // - ); - -final Parser number = // - (minus.opt() & decimal) // minus?, decimal - .map((r) => num.parse(r.span!.text)); - -void main() { - while (true) { - stdout.write('Enter a number: '); - var line = stdin.readLineSync()!; - var scanner = SpanScanner(line, sourceUrl: 'stdin'); - var result = number.parse(scanner); - - if (!result.successful) { - for (var error in result.errors) { - stderr.writeln(error.toolString); - stderr.writeln(error.span!.highlight(color: true)); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/query_string.dart b/packages/combinator/example/query_string.dart deleted file mode 100644 index 4a42fff7..00000000 --- a/packages/combinator/example/query_string.dart +++ /dev/null @@ -1,45 +0,0 @@ -// For some reason, this cannot be run in checked mode??? - -import 'dart:io'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -final Parser key = - match(RegExp(r'[^=&\n]+'), errorMessage: 'Missing k/v') - .value((r) => r.span!.text); - -final Parser value = key.map((r) => Uri.decodeQueryComponent(r.value!)); - -final Parser pair = chain([ - key, - match('='), - value, -]).map((r) { - return { - r.value![0]: r.value![2], - }; -}); - -final Parser pairs = pair - .separatedBy(match(r'&')) - .map((r) => r.value!.reduce((a, b) => a..addAll(b))); - -final Parser queryString = pairs.opt(); - -void main() { - while (true) { - stdout.write('Enter a query string: '); - var line = stdin.readLineSync()!; - var scanner = SpanScanner(line, sourceUrl: 'stdin'); - var result = pairs.parse(scanner); - - if (!result.successful) { - for (var error in result.errors) { - print(error.toolString); - print(error.span!.highlight(color: true)); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/sexp.dart b/packages/combinator/example/sexp.dart deleted file mode 100644 index 9b51d626..00000000 --- a/packages/combinator/example/sexp.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'dart:collection'; -import 'dart:io'; -import 'dart:math'; -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; -import 'package:tuple/tuple.dart'; - -void main() { - var expr = reference(); - var symbols = {}; - - void registerFunction(String name, int nArgs, Function(List) f) { - symbols[name] = Tuple2(nArgs, f); - } - - registerFunction('**', 2, (args) => pow(args[0], args[1])); - registerFunction('*', 2, (args) => args[0] * args[1]); - registerFunction('/', 2, (args) => args[0] / args[1]); - registerFunction('%', 2, (args) => args[0] % args[1]); - registerFunction('+', 2, (args) => args[0] + args[1]); - registerFunction('-', 2, (args) => args[0] - args[1]); - registerFunction('.', 1, (args) => args[0].toDouble()); - registerFunction('print', 1, (args) { - print(args[0]); - return args[0]; - }); - - var number = - match(RegExp(r'[0-9]+(\.[0-9]+)?'), errorMessage: 'Expected a number.') - .map((r) => num.parse(r.span!.text)); - - var id = match( - RegExp( - r'[A-Za-z_!\\$",\\+-\\./:;\\?<>%&\\*@\[\]\\{\}\\|`\\^~][A-Za-z0-9_!\\$",\\+-\\./:;\\?<>%&\*@\[\]\\{\}\\|`\\^~]*'), - errorMessage: 'Expected an ID') - .map((r) => symbols[r.span!.text] ??= - throw "Undefined symbol: '${r.span!.text}'"); - - var atom = number.castDynamic().or(id); - - var list = expr.space().times(2, exact: false).map((r) { - try { - var out = []; - var q = Queue.from(r.value!.reversed); - - while (q.isNotEmpty) { - var current = q.removeFirst(); - if (current is! Tuple2) { - out.insert(0, current); - } else { - var args = []; - for (var i = 0; i < (current.item1 as num); i++) { - args.add(out.removeLast()); - } - out.add(current.item2(args)); - } - } - - return out.length == 1 ? out.first : out; - } catch (_) { - return []; - } - }); - - expr.parser = longest([ - list, - atom, - expr.parenthesized(), - ]); //list | atom | expr.parenthesized(); - - while (true) { - stdout.write('> '); - var line = stdin.readLineSync()!; - var result = expr.parse(SpanScanner(line)); - - if (result.errors.isNotEmpty) { - for (var error in result.errors) { - print(error.toolString); - print(error.message); - } - } else { - print(result.value); - } - } -} diff --git a/packages/combinator/example/tuple.dart b/packages/combinator/example/tuple.dart deleted file mode 100644 index 188ced83..00000000 --- a/packages/combinator/example/tuple.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:string_scanner/string_scanner.dart'; - -void main() { - var pub = match('pub').map((r) => r.span!.text).space(); - var dart = match('dart').map((r) => 24).space(); - var lang = match('lang').map((r) => true).space(); - - // Parses a Tuple3 - var grammar = tuple3(pub, dart, lang); - - var scanner = SpanScanner('pub dart lang'); - print(grammar.parse(scanner).value); -} diff --git a/packages/combinator/lib/angel3_combinator.dart b/packages/combinator/lib/angel3_combinator.dart deleted file mode 100644 index 79e4c074..00000000 --- a/packages/combinator/lib/angel3_combinator.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'src/combinator/combinator.dart'; -export 'src/error.dart'; diff --git a/packages/combinator/lib/src/combinator/advance.dart b/packages/combinator/lib/src/combinator/advance.dart deleted file mode 100644 index 01506dc2..00000000 --- a/packages/combinator/lib/src/combinator/advance.dart +++ /dev/null @@ -1,26 +0,0 @@ -part of lex.src.combinator; - -class _Advance extends Parser { - final Parser parser; - final int amount; - - _Advance(this.parser, this.amount); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()).change(parser: this); - if (result.successful) args.scanner.position += amount; - return result; - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('advance($amount) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/any.dart b/packages/combinator/lib/src/combinator/any.dart deleted file mode 100644 index 45bc107a..00000000 --- a/packages/combinator/lib/src/combinator/any.dart +++ /dev/null @@ -1,85 +0,0 @@ -part of lex.src.combinator; - -/// Matches any one of the given [parsers]. -/// -/// If [backtrack] is `true` (default), a failed parse will not modify the scanner state. -/// -/// You can provide a custom [errorMessage]. You can set it to `false` to not -/// generate any error at all. -Parser any(Iterable> parsers, - {bool backtrack = true, errorMessage, SyntaxErrorSeverity? severity}) { - return _Any(parsers, backtrack != false, errorMessage, - severity ?? SyntaxErrorSeverity.error); -} - -class _Any extends Parser { - final Iterable> parsers; - final bool backtrack; - final errorMessage; - final SyntaxErrorSeverity severity; - - _Any(this.parsers, this.backtrack, this.errorMessage, this.severity); - - @override - ParseResult _parse(ParseArgs args) { - var inactive = parsers - .where((p) => !args.trampoline.isActive(p, args.scanner.position)); - - if (inactive.isEmpty) { - return ParseResult(args.trampoline, args.scanner, this, false, []); - } - - var errors = []; - var replay = args.scanner.position; - - for (var parser in inactive) { - var result = parser._parse(args.increaseDepth()); - - if (result.successful) { - return result; - } else { - if (backtrack) args.scanner.position = replay; - if (parser is _Alt) errors.addAll(result.errors); - } - } - - if (errorMessage != false) { - errors.add( - SyntaxError( - severity, - errorMessage?.toString() ?? - 'No match found for ${parsers.length} alternative(s)', - args.scanner.emptySpan, - ), - ); - } - - return ParseResult(args.trampoline, args.scanner, this, false, errors); - } - - @override - ParseResult __parse(ParseArgs args) { - // Never called - throw ArgumentError('[Combinator] Invalid method call'); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('any(${parsers.length}) (') - ..indent(); - var i = 1; - - for (var parser in parsers) { - buffer - ..writeln('#${i++}:') - ..indent(); - parser.stringify(buffer); - buffer.outdent(); - } - - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/cache.dart b/packages/combinator/lib/src/combinator/cache.dart deleted file mode 100644 index b07b38e0..00000000 --- a/packages/combinator/lib/src/combinator/cache.dart +++ /dev/null @@ -1,26 +0,0 @@ -part of lex.src.combinator; - -class _Cache extends Parser { - final Map> _cache = {}; - final Parser parser; - - _Cache(this.parser); - - @override - ParseResult __parse(ParseArgs args) { - return _cache.putIfAbsent(args.scanner.position, () { - return parser._parse(args.increaseDepth()); - }).change(parser: this); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('cache(${_cache.length}) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/cast.dart b/packages/combinator/lib/src/combinator/cast.dart deleted file mode 100644 index 9b531d43..00000000 --- a/packages/combinator/lib/src/combinator/cast.dart +++ /dev/null @@ -1,63 +0,0 @@ -part of lex.src.combinator; - -class _Cast extends Parser { - final Parser parser; - - _Cast(this.parser); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - return ParseResult( - args.trampoline, - args.scanner, - this, - result.successful, - result.errors, - span: result.span, - value: result.value as U?, - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('cast<$U> (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} - -class _CastDynamic extends Parser { - final Parser parser; - - _CastDynamic(this.parser); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - return ParseResult( - args.trampoline, - args.scanner, - this, - result.successful, - result.errors, - span: result.span, - value: result.value, - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('cast (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/chain.dart b/packages/combinator/lib/src/combinator/chain.dart deleted file mode 100644 index 101836b4..00000000 --- a/packages/combinator/lib/src/combinator/chain.dart +++ /dev/null @@ -1,111 +0,0 @@ -part of lex.src.combinator; - -/// Expects to parse a sequence of [parsers]. -/// -/// If [failFast] is `true` (default), then the first failure to parse will abort the parse. -ListParser chain(Iterable> parsers, - {bool failFast = true, SyntaxErrorSeverity? severity}) { - return _Chain( - parsers, failFast != false, severity ?? SyntaxErrorSeverity.error); -} - -class _Alt extends Parser { - final Parser parser; - final String? errorMessage; - final SyntaxErrorSeverity severity; - - _Alt(this.parser, this.errorMessage, this.severity); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - return result.successful - ? result - : result.addErrors([ - SyntaxError( - severity, errorMessage, result.span ?? args.scanner.emptySpan), - ]); - } - - @override - void stringify(CodeBuffer buffer) { - parser.stringify(buffer); - } -} - -class _Chain extends ListParser { - final Iterable> parsers; - final bool failFast; - final SyntaxErrorSeverity severity; - - _Chain(this.parsers, this.failFast, this.severity); - - @override - ParseResult> __parse(ParseArgs args) { - var errors = []; - var results = []; - var spans = []; - var successful = true; - - for (var parser in parsers) { - var result = parser._parse(args.increaseDepth()); - - if (!result.successful) { - if (parser is _Alt) errors.addAll(result.errors); - - if (failFast) { - return ParseResult( - args.trampoline, args.scanner, this, false, result.errors); - } - - successful = false; - } - - if (result.value != null) { - results.add(result.value!); - } else { - results.add('NULL' as T); - } - - if (result.span != null) { - spans.add(result.span!); - } - } - - FileSpan? span; - - if (spans.isNotEmpty) { - span = spans.reduce((a, b) => a.expand(b)); - } - - return ParseResult>( - args.trampoline, - args.scanner, - this, - successful, - errors, - span: span, - value: List.unmodifiable(results), - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('chain(${parsers.length}) (') - ..indent(); - var i = 1; - - for (var parser in parsers) { - buffer - ..writeln('#${i++}:') - ..indent(); - parser.stringify(buffer); - buffer.outdent(); - } - - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/check.dart b/packages/combinator/lib/src/combinator/check.dart deleted file mode 100644 index a6f7bedc..00000000 --- a/packages/combinator/lib/src/combinator/check.dart +++ /dev/null @@ -1,42 +0,0 @@ -part of lex.src.combinator; - -class _Check extends Parser { - final Parser parser; - final Matcher matcher; - final String? errorMessage; - final SyntaxErrorSeverity severity; - - _Check(this.parser, this.matcher, this.errorMessage, this.severity); - - @override - ParseResult __parse(ParseArgs args) { - var matchState = {}; - var result = parser._parse(args.increaseDepth()).change(parser: this); - if (!result.successful) { - return result; - } else if (!matcher.matches(result.value, matchState)) { - return result.change(successful: false).addErrors([ - SyntaxError( - severity, - errorMessage ?? - matcher.describe(StringDescription('Expected ')).toString() + '.', - result.span, - ), - ]); - } else { - return result; - } - } - - @override - void stringify(CodeBuffer buffer) { - var d = matcher.describe(StringDescription()); - buffer - ..writeln('check($d) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/combinator.dart b/packages/combinator/lib/src/combinator/combinator.dart deleted file mode 100644 index 717365ab..00000000 --- a/packages/combinator/lib/src/combinator/combinator.dart +++ /dev/null @@ -1,394 +0,0 @@ -library lex.src.combinator; - -import 'dart:collection'; - -import 'package:angel3_code_buffer/angel3_code_buffer.dart'; -import 'package:matcher/matcher.dart'; -import 'package:source_span/source_span.dart'; -import 'package:string_scanner/string_scanner.dart'; -import 'package:tuple/tuple.dart'; -import '../error.dart'; - -part 'any.dart'; - -part 'advance.dart'; - -part 'cache.dart'; - -part 'cast.dart'; - -part 'chain.dart'; - -part 'check.dart'; - -part 'compare.dart'; - -part 'fold_errors.dart'; - -part 'index.dart'; - -part 'longest.dart'; - -part 'map.dart'; - -part 'match.dart'; - -part 'max_depth.dart'; - -part 'negate.dart'; - -part 'opt.dart'; - -part 'recursion.dart'; - -part 'reduce.dart'; - -part 'reference.dart'; - -part 'repeat.dart'; - -part 'safe.dart'; - -part 'to_list.dart'; - -part 'util.dart'; - -part 'value.dart'; - -class ParseArgs { - final Trampoline trampoline; - final SpanScanner scanner; - final int depth; - - ParseArgs(this.trampoline, this.scanner, this.depth); - - ParseArgs increaseDepth() => ParseArgs(trampoline, scanner, depth + 1); -} - -/// A parser combinator, which can parse very complicated grammars in a manageable manner. -abstract class Parser { - ParseResult __parse(ParseArgs args); - - ParseResult _parse(ParseArgs args) { - var pos = args.scanner.position; - - if (args.trampoline.hasMemoized(this, pos)) { - return args.trampoline.getMemoized(this, pos); - } - - if (args.trampoline.isActive(this, pos)) { - return ParseResult(args.trampoline, args.scanner, this, false, []); - } - - args.trampoline.enter(this, pos); - var result = __parse(args); - args.trampoline.memoize(this, pos, result); - args.trampoline.exit(this); - return result; - } - - /// Parses text from a [SpanScanner]. - ParseResult parse(SpanScanner scanner, [int depth = 1]) { - var args = ParseArgs(Trampoline(), scanner, depth); - return _parse(args); - } - - /// Skips forward a certain amount of steps after parsing, if it was successful. - Parser forward(int amount) => _Advance(this, amount); - - /// Moves backward a certain amount of steps after parsing, if it was successful. - Parser back(int amount) => _Advance(this, amount * -1); - - /// Casts this parser to produce [U] objects. - Parser cast() => _Cast(this); - - /// Casts this parser to produce [dynamic] objects. - Parser castDynamic() => _CastDynamic(this); - - /// Runs the given function, which changes the returned [ParseResult] into one relating to a [U] object. - Parser change(ParseResult Function(ParseResult) f) { - return _Change(this, f); - } - - /// Validates the parse result against a [Matcher]. - /// - /// You can provide a custom [errorMessage]. - Parser check(Matcher matcher, - {String? errorMessage, SyntaxErrorSeverity? severity}) => - _Check( - this, matcher, errorMessage, severity ?? SyntaxErrorSeverity.error); - - /// Binds an [errorMessage] to a copy of this parser. - Parser error({String? errorMessage, SyntaxErrorSeverity? severity}) => - _Alt(this, errorMessage, severity ?? SyntaxErrorSeverity.error); - - /// Removes multiple errors that occur in the same spot; this can reduce noise in parser output. - Parser foldErrors({bool Function(SyntaxError a, SyntaxError b)? equal}) { - equal ??= (b, e) => b.span?.start.offset == e.span?.start.offset; - return _FoldErrors(this, equal); - } - - /// Transforms the parse result using a unary function. - Parser map(U Function(ParseResult) f) { - return _Map(this, f); - } - - /// Prevents recursion past a certain [depth], preventing stack overflow errors. - Parser maxDepth(int depth) => _MaxDepth(this, depth); - - Parser operator ~() => negate(); - - /// Ensures this pattern is not matched. - /// - /// You can provide an [errorMessage]. - Parser negate( - {String errorMessage = 'Negate error', - SyntaxErrorSeverity severity = SyntaxErrorSeverity.error}) => - _Negate(this, errorMessage, severity); - - /// Caches the results of parse attempts at various locations within the source text. - /// - /// Use this to prevent excessive recursion. - Parser cache() => _Cache(this); - - Parser operator &(Parser other) => and(other); - - /// Consumes `this` and another parser, but only considers the result of `this` parser. - Parser and(Parser other) => then(other).change((r) { - return ParseResult( - r.trampoline, - r.scanner, - this, - r.successful, - r.errors, - span: r.span, - value: (r.value != null ? r.value![0] : r.value) as T?, - ); - }); - - Parser operator |(Parser other) => or(other); - - /// Shortcut for [or]-ing two parsers. - Parser or(Parser other) => any([this, other]); - - /// Parses this sequence one or more times. - ListParser plus() => times(1, exact: false); - - /// Safely escapes this parser when an error occurs. - /// - /// The generated parser only runs once; repeated uses always exit eagerly. - Parser safe( - {bool backtrack = true, - String errorMessage = 'error', - SyntaxErrorSeverity? severity}) => - _Safe( - this, backtrack, errorMessage, severity ?? SyntaxErrorSeverity.error); - - Parser> separatedByComma() => - separatedBy(match>(',').space()); - - /// Expects to see an infinite amounts of the pattern, separated by the [other] pattern. - /// - /// Use this as a shortcut to parse arrays, parameter lists, etc. - Parser> separatedBy(Parser other) { - var suffix = other.then(this).index(1).cast(); - return then(suffix.star()).map((r) { - var v = r.value; - if (v == null || v.length < 2) { - return []; - } - var preceding = v.isEmpty ? [] : (v[0] == null ? [] : [v[0]]); - var out = List.from(preceding); - if (v[1] != null && v[1] != 'NULL') { - v[1].forEach((element) { - out.add(element as T); - }); - } - return out; - }); - } - - Parser surroundedByCurlyBraces({required T defaultValue}) => opt() - .surroundedBy(match('{').space(), match('}').space()) - .map((r) => r.value ?? defaultValue); - - Parser surroundedBySquareBrackets({required T defaultValue}) => opt() - .surroundedBy(match('[').space(), match(']').space()) - .map((r) => r.value ?? defaultValue); - - /// Expects to see the pattern, surrounded by the others. - /// - /// If no [right] is provided, it expects to see the same pattern on both sides. - /// Use this parse things like parenthesized expressions, arrays, etc. - Parser surroundedBy(Parser left, [Parser? right]) { - return chain([ - left, - this, - right ?? left, - ]).index(1).castDynamic().cast(); - } - - /// Parses `this`, either as-is or wrapped in parentheses. - Parser maybeParenthesized() { - return any([parenthesized(), this]); - } - - /// Parses `this`, wrapped in parentheses. - Parser parenthesized() => - surroundedBy(match('(').space(), match(')').space()); - - /// Consumes any trailing whitespace. - Parser space() => trail(RegExp(r'[ \n\r\t]+')); - - /// Consumes 0 or more instance(s) of this parser. - ListParser star({bool backtrack = true}) => - times(1, exact: false, backtrack: backtrack).opt(); - - /// Shortcut for [chain]-ing two parsers together. - ListParser then(Parser other) => chain([this, other]); - - /// Casts this instance into a [ListParser]. - ListParser toList() => _ToList(this); - - /// Consumes and ignores any trailing occurrences of [pattern]. - Parser trail(Pattern pattern) => - then(match(pattern).opt()).first().cast(); - - /// Expect this pattern a certain number of times. - /// - /// If [exact] is `false` (default: `true`), then the generated parser will accept - /// an infinite amount of occurrences after the specified [count]. - /// - /// You can provide custom error messages for when there are [tooFew] or [tooMany] occurrences. - ListParser times(int count, - {bool exact = true, - String tooFew = 'Too few', - String tooMany = 'Too many', - bool backtrack = true, - SyntaxErrorSeverity? severity}) { - return _Repeat(this, count, exact, tooFew, tooMany, backtrack, - severity ?? SyntaxErrorSeverity.error); - } - - /// Produces an optional copy of this parser. - /// - /// If [backtrack] is `true` (default), then a failed parse will not - /// modify the scanner state. - Parser opt({bool backtrack = true}) => _Opt(this, backtrack); - - /// Sets the value of the [ParseResult]. - Parser value(T Function(ParseResult) f) { - return _Value(this, f); - } - - /// Prints a representation of this parser, ideally without causing a stack overflow. - void stringify(CodeBuffer buffer); -} - -/// A [Parser] that produces [List]s of a type [T]. -abstract class ListParser extends Parser> { - /// Shortcut for calling [index] with `0`. - Parser first() => index(0); - - /// Modifies this parser to only return the value at the given index [i]. - Parser index(int i) => _Index(this, i); - - /// Shortcut for calling [index] with the greatest-possible index. - Parser last() => index(-1); - - /// Modifies this parser to call `List.reduce` on the parsed values. - Parser reduce(T Function(T, T) combine) => _Reduce(this, combine); - - /// Sorts the parsed values, using the given [Comparator]. - ListParser sort(Comparator compare) => _Compare(this, compare); - - @override - ListParser opt({bool backtrack = true}) => _ListOpt(this, backtrack); - - /// Modifies this parser, returning only the values that match a predicate. - Parser> where(bool Function(T) f) => - map>((r) => r.value?.where(f).toList() ?? []); - - /// Condenses a [ListParser] into having a value of the combined span's text. - Parser flatten() => map((r) => r.span?.text ?? ''); -} - -/// Prevents stack overflow in recursive parsers. -class Trampoline { - final Map> _active = {}; - final Map>> _memo = {}; - - bool hasMemoized(Parser parser, int position) { - var list = _memo[parser]; - return list?.any((t) => t.item1 == position) == true; - } - - ParseResult getMemoized(Parser parser, int position) { - return _memo[parser]?.firstWhere((t) => t.item1 == position).item2 - as ParseResult; - } - - void memoize(Parser parser, int position, ParseResult? result) { - if (result != null) { - var list = _memo.putIfAbsent(parser, () => []); - var tuple = Tuple2(position, result); - if (!list.contains(tuple)) list.add(tuple); - } - } - - bool isActive(Parser parser, int position) { - if (!_active.containsKey(parser)) { - return false; - } - var q = _active[parser]!; - if (q.isEmpty) return false; - //return q.contains(position); - return q.first == position; - } - - void enter(Parser parser, int position) { - _active.putIfAbsent(parser, () => Queue()).addFirst(position); - } - - void exit(Parser parser) { - if (_active.containsKey(parser)) _active[parser]?.removeFirst(); - } -} - -/// The result generated by a [Parser]. -class ParseResult { - final Parser parser; - final bool successful; - final Iterable errors; - final FileSpan? span; - final T? value; - final SpanScanner scanner; - final Trampoline trampoline; - - ParseResult( - this.trampoline, this.scanner, this.parser, this.successful, this.errors, - {this.span, this.value}); - - ParseResult change( - {Parser? parser, - bool? successful, - Iterable errors = const [], - FileSpan? span, - T? value}) { - return ParseResult( - trampoline, - scanner, - parser ?? this.parser, - successful ?? this.successful, - errors.isNotEmpty ? errors : this.errors, - span: span ?? this.span, - value: value ?? this.value, - ); - } - - ParseResult addErrors(Iterable errors) { - return change( - errors: List.from(this.errors)..addAll(errors), - ); - } -} diff --git a/packages/combinator/lib/src/combinator/compare.dart b/packages/combinator/lib/src/combinator/compare.dart deleted file mode 100644 index 3a5e36d5..00000000 --- a/packages/combinator/lib/src/combinator/compare.dart +++ /dev/null @@ -1,38 +0,0 @@ -part of lex.src.combinator; - -class _Compare extends ListParser { - final ListParser parser; - final Comparator compare; - - _Compare(this.parser, this.compare); - - @override - ParseResult> __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - if (!result.successful) return result; - - result = result.change( - value: result.value?.isNotEmpty == true ? result.value : []); - result = result.change(value: List.from(result.value!)); - return ParseResult>( - args.trampoline, - args.scanner, - this, - true, - [], - span: result.span, - value: result.value?..sort(compare), - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('sort($compare) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/fold_errors.dart b/packages/combinator/lib/src/combinator/fold_errors.dart deleted file mode 100644 index 6d15c69a..00000000 --- a/packages/combinator/lib/src/combinator/fold_errors.dart +++ /dev/null @@ -1,29 +0,0 @@ -part of lex.src.combinator; - -class _FoldErrors extends Parser { - final Parser parser; - final bool Function(SyntaxError, SyntaxError) equal; - - _FoldErrors(this.parser, this.equal); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()).change(parser: this); - var errors = result.errors.fold>([], (out, e) { - if (!out.any((b) => equal(e, b))) out.add(e); - return out; - }); - return result.change(errors: errors); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('fold errors (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/index.dart b/packages/combinator/lib/src/combinator/index.dart deleted file mode 100644 index 41d4460a..00000000 --- a/packages/combinator/lib/src/combinator/index.dart +++ /dev/null @@ -1,52 +0,0 @@ -part of lex.src.combinator; - -class _Index extends Parser { - final ListParser parser; - final int index; - - _Index(this.parser, this.index); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - Object? value; - - if (result.successful) { - var vList = result.value; - if (vList == null) { - throw ArgumentError('ParseResult is null'); - } - if (index == -1) { - value = vList.last; - } else { - if (index < vList.length) { -// print(">>>>Index: $index, Size: ${vList.length}"); -// value = -// index == -1 ? result.value!.last : result.value!.elementAt(index); - value = result.value!.elementAt(index); - } - } - } - - return ParseResult( - args.trampoline, - args.scanner, - this, - result.successful, - result.errors, - span: result.span, - value: value as T?, - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('index($index) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/longest.dart b/packages/combinator/lib/src/combinator/longest.dart deleted file mode 100644 index 36d9652e..00000000 --- a/packages/combinator/lib/src/combinator/longest.dart +++ /dev/null @@ -1,115 +0,0 @@ -part of lex.src.combinator; - -/// Matches any one of the given [parsers]. -/// -/// You can provide a custom [errorMessage]. -Parser longest(Iterable> parsers, - {Object? errorMessage, SyntaxErrorSeverity? severity}) { - return _Longest(parsers, errorMessage, severity ?? SyntaxErrorSeverity.error); -} - -class _Longest extends Parser { - final Iterable> parsers; - final Object? errorMessage; - final SyntaxErrorSeverity severity; - - _Longest(this.parsers, this.errorMessage, this.severity); - - @override - ParseResult _parse(ParseArgs args) { - var inactive = parsers - .toList() - .where((p) => !args.trampoline.isActive(p, args.scanner.position)); - - if (inactive.isEmpty) { - return ParseResult(args.trampoline, args.scanner, this, false, []); - } - - var replay = args.scanner.position; - var errors = []; - var results = >[]; - - for (var parser in inactive) { - var result = parser._parse(args.increaseDepth()); - - if (result.successful && result.span != null) { - results.add(result); - } else if (parser is _Alt) errors.addAll(result.errors); - - args.scanner.position = replay; - } - - if (results.isNotEmpty) { - results.sort((a, b) => b.span!.length.compareTo(a.span!.length)); - args.scanner.scan(results.first.span!.text); - return results.first; - } - - if (errorMessage != false) { - errors.add( - SyntaxError( - severity, - errorMessage?.toString() ?? - 'No match found for ${parsers.length} alternative(s)', - args.scanner.emptySpan, - ), - ); - } - - return ParseResult(args.trampoline, args.scanner, this, false, errors); - } - - @override - ParseResult __parse(ParseArgs args) { - var replay = args.scanner.position; - var errors = []; - var results = >[]; - - for (var parser in parsers) { - var result = parser._parse(args.increaseDepth()); - - if (result.successful) { - results.add(result); - } else if (parser is _Alt) errors.addAll(result.errors); - - args.scanner.position = replay; - } - - if (results.isNotEmpty) { - results.sort((a, b) => b.span!.length.compareTo(a.span!.length)); - args.scanner.scan(results.first.span!.text); - return results.first; - } - - errors.add( - SyntaxError( - severity, - errorMessage?.toString() ?? - 'No match found for ${parsers.length} alternative(s)', - args.scanner.emptySpan, - ), - ); - - return ParseResult(args.trampoline, args.scanner, this, false, errors); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('longest(${parsers.length}) (') - ..indent(); - var i = 1; - - for (var parser in parsers) { - buffer - ..writeln('#${i++}:') - ..indent(); - parser.stringify(buffer); - buffer.outdent(); - } - - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/map.dart b/packages/combinator/lib/src/combinator/map.dart deleted file mode 100644 index 4dfb326d..00000000 --- a/packages/combinator/lib/src/combinator/map.dart +++ /dev/null @@ -1,56 +0,0 @@ -part of lex.src.combinator; - -class _Map extends Parser { - final Parser parser; - final U Function(ParseResult) f; - - _Map(this.parser, this.f); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - return ParseResult( - args.trampoline, - args.scanner, - this, - result.successful, - result.errors, - span: result.span, - value: result.successful ? f(result) : null, - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('map<$U> (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} - -class _Change extends Parser { - final Parser parser; - final ParseResult Function(ParseResult) f; - - _Change(this.parser, this.f); - - @override - ParseResult __parse(ParseArgs args) { - return f(parser._parse(args.increaseDepth())).change(parser: this); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('change($f) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/match.dart b/packages/combinator/lib/src/combinator/match.dart deleted file mode 100644 index 837c306d..00000000 --- a/packages/combinator/lib/src/combinator/match.dart +++ /dev/null @@ -1,41 +0,0 @@ -part of lex.src.combinator; - -/// Expects to match a given [pattern]. If it is not matched, you can provide a custom [errorMessage]. -Parser match(Pattern pattern, - {String? errorMessage, SyntaxErrorSeverity? severity}) => - _Match(pattern, errorMessage, severity ?? SyntaxErrorSeverity.error); - -class _Match extends Parser { - final Pattern pattern; - final String? errorMessage; - final SyntaxErrorSeverity severity; - - _Match(this.pattern, this.errorMessage, this.severity); - - @override - ParseResult __parse(ParseArgs args) { - var scanner = args.scanner; - if (!scanner.scan(pattern)) { - return ParseResult(args.trampoline, scanner, this, false, [ - SyntaxError( - severity, - errorMessage ?? 'Expected "$pattern".', - scanner.emptySpan, - ), - ]); - } - return ParseResult( - args.trampoline, - scanner, - this, - true, - [], - span: scanner.lastSpan, - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer.writeln('match($pattern)'); - } -} diff --git a/packages/combinator/lib/src/combinator/max_depth.dart b/packages/combinator/lib/src/combinator/max_depth.dart deleted file mode 100644 index 42befcff..00000000 --- a/packages/combinator/lib/src/combinator/max_depth.dart +++ /dev/null @@ -1,28 +0,0 @@ -part of lex.src.combinator; - -class _MaxDepth extends Parser { - final Parser parser; - final int cap; - - _MaxDepth(this.parser, this.cap); - - @override - ParseResult __parse(ParseArgs args) { - if (args.depth > cap) { - return ParseResult(args.trampoline, args.scanner, this, false, []); - } - - return parser._parse(args.increaseDepth()); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('max depth($cap) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/negate.dart b/packages/combinator/lib/src/combinator/negate.dart deleted file mode 100644 index b507bdcc..00000000 --- a/packages/combinator/lib/src/combinator/negate.dart +++ /dev/null @@ -1,51 +0,0 @@ -part of lex.src.combinator; - -class _Negate extends Parser { - final Parser parser; - final String? errorMessage; - final SyntaxErrorSeverity severity; - - _Negate(this.parser, this.errorMessage, this.severity); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()).change(parser: this); - - if (!result.successful) { - return ParseResult( - args.trampoline, - args.scanner, - this, - true, - [], - span: result.span ?? args.scanner.lastSpan ?? args.scanner.emptySpan, - value: result.value, - ); - } - - result = result.change(successful: false); - - if (errorMessage != null) { - result = result.addErrors([ - SyntaxError( - severity, - errorMessage, - result.span, - ), - ]); - } - - return result; - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('negate (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/opt.dart b/packages/combinator/lib/src/combinator/opt.dart deleted file mode 100644 index 3f31c995..00000000 --- a/packages/combinator/lib/src/combinator/opt.dart +++ /dev/null @@ -1,57 +0,0 @@ -part of lex.src.combinator; - -class _Opt extends Parser { - final Parser parser; - final bool backtrack; - - _Opt(this.parser, this.backtrack); - - @override - ParseResult __parse(ParseArgs args) { - var replay = args.scanner.position; - var result = parser._parse(args.increaseDepth()); - - if (!result.successful) args.scanner.position = replay; - - return result.change(parser: this, successful: true); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('optional (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} - -class _ListOpt extends ListParser { - final ListParser parser; - final bool backtrack; - - _ListOpt(this.parser, this.backtrack); - - @override - ParseResult> __parse(ParseArgs args) { - var replay = args.scanner.position; - var result = parser._parse(args.increaseDepth()); - - if (!result.successful) args.scanner.position = replay; - - return result.change(parser: this, successful: true); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('optional (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/recursion.dart b/packages/combinator/lib/src/combinator/recursion.dart deleted file mode 100644 index 76516943..00000000 --- a/packages/combinator/lib/src/combinator/recursion.dart +++ /dev/null @@ -1,142 +0,0 @@ -part of lex.src.combinator; - -/* -/// Handles left recursion in a grammar using the Pratt algorithm. -class Recursion { - Iterable> prefix; - Map)> infix; - Map)> postfix; - - Recursion({this.prefix, this.infix, this.postfix}) { - prefix ??= []; - infix ??= {}; - postfix ??= {}; - } - - Parser precedence(int p) => _Precedence(this, p); - - void stringify(CodeBuffer buffer) { - buffer - ..writeln('recursion (') - ..indent() - ..writeln('prefix(${prefix.length}') - ..writeln('infix(${infix.length}') - ..writeln('postfix(${postfix.length}') - ..outdent() - ..writeln(')'); - } -} - -class _Precedence extends Parser { - final Recursion r; - final int precedence; - - _Precedence(this.r, this.precedence); - - @override - ParseResult __parse(ParseArgs args) { - int replay = args.scanner.position; - var errors = []; - var start = args.scanner.state; - var reversedKeys = r.infix.keys.toList().reversed; - - for (var pre in r.prefix) { - var result = pre._parse(args.increaseDepth()), originalResult = result; - - if (!result.successful) { - if (pre is _Alt) errors.addAll(result.errors); - args.scanner.position = replay; - } else { - var left = result.value; - replay = args.scanner.position; - //print('${result.span.text}:\n' + scanner.emptySpan.highlight()); - - while (true) { - bool matched = false; - - //for (int i = 0; i < r.infix.length; i++) { - for (int i = r.infix.length - 1; i >= 0; i--) { - //var fix = r.infix.keys.elementAt(r.infix.length - i - 1); - var fix = reversedKeys.elementAt(i); - - if (i < precedence) continue; - - var result = fix._parse(args.increaseDepth()); - - if (!result.successful) { - if (fix is _Alt) errors.addAll(result.errors); - // If this is the last alternative and it failed, don't continue looping. - //if (true || i + 1 < r.infix.length) - args.scanner.position = replay; - } else { - //print('FOUND $fix when left was $left'); - //print('$i vs $precedence\n${originalResult.span.highlight()}'); - result = r.precedence(i)._parse(args.increaseDepth()); - - if (!result.successful) { - } else { - matched = false; - var old = left; - left = r.infix[fix](left, result.value, result); - print( - '$old $fix ${result.value} = $left\n${result.span.highlight()}'); - break; - } - } - } - - if (!matched) break; - } - - replay = args.scanner.position; - //print('f ${result.span.text}'); - - for (var post in r.postfix.keys) { - var result = pre._parse(args.increaseDepth()); - - if (!result.successful) { - if (post is _Alt) errors.addAll(result.errors); - args.scanner.position = replay; - } else { - left = r.infix[post](left, originalResult.value, result); - } - } - - if (!args.scanner.isDone) { - // If we're not done scanning, then we need some sort of guard to ensure the - // that this exact parser does not run again in the exact position. - } - return ParseResult( - args.trampoline, - args.scanner, - this, - true, - errors, - value: left, - span: args.scanner.spanFrom(start), - ); - } - } - - return ParseResult( - args.trampoline, - args.scanner, - this, - false, - errors, - span: args.scanner.spanFrom(start), - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('precedence($precedence) (') - ..indent(); - r.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} -*/ diff --git a/packages/combinator/lib/src/combinator/reduce.dart b/packages/combinator/lib/src/combinator/reduce.dart deleted file mode 100644 index a8779b4b..00000000 --- a/packages/combinator/lib/src/combinator/reduce.dart +++ /dev/null @@ -1,46 +0,0 @@ -part of lex.src.combinator; - -class _Reduce extends Parser { - final ListParser parser; - final T Function(T, T) combine; - - _Reduce(this.parser, this.combine); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - - if (!result.successful) { - return ParseResult( - args.trampoline, - args.scanner, - this, - false, - result.errors, - ); - } - - result = result.change( - value: result.value?.isNotEmpty == true ? result.value : []); - return ParseResult( - args.trampoline, - args.scanner, - this, - result.successful, - [], - span: result.span, - value: result.value!.isEmpty ? null : result.value!.reduce(combine), - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('reduce($combine) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/reference.dart b/packages/combinator/lib/src/combinator/reference.dart deleted file mode 100644 index 5088c4ac..00000000 --- a/packages/combinator/lib/src/combinator/reference.dart +++ /dev/null @@ -1,44 +0,0 @@ -part of lex.src.combinator; - -Reference reference() => Reference._(); - -class Reference extends Parser { - Parser? _parser; - bool printed = false; - - Reference._(); - - set parser(Parser value) { - if (_parser != null) { - throw StateError('There is already a parser assigned to this reference.'); - } - _parser = value; - } - - @override - ParseResult __parse(ParseArgs args) { - if (_parser == null) { - throw StateError('There is no parser assigned to this reference.'); - } - return _parser!._parse(args); - } - - @override - ParseResult _parse(ParseArgs args) { - if (_parser == null) { - throw StateError('There is no parser assigned to this reference.'); - } - return _parser!._parse(args); - } - - @override - void stringify(CodeBuffer buffer) { - if (_parser == null) { - buffer.writeln('(undefined reference <$T>)'); - } else if (!printed) { - _parser!.stringify(buffer); - } - printed = true; - buffer.writeln('(previously printed reference)'); - } -} diff --git a/packages/combinator/lib/src/combinator/repeat.dart b/packages/combinator/lib/src/combinator/repeat.dart deleted file mode 100644 index 13dd9f24..00000000 --- a/packages/combinator/lib/src/combinator/repeat.dart +++ /dev/null @@ -1,89 +0,0 @@ -part of lex.src.combinator; - -class _Repeat extends ListParser { - final Parser parser; - final int count; - final bool exact, backtrack; - final String tooFew; - final String tooMany; - final SyntaxErrorSeverity severity; - - _Repeat(this.parser, this.count, this.exact, this.tooFew, this.tooMany, - this.backtrack, this.severity); - - @override - ParseResult> __parse(ParseArgs args) { - var errors = []; - var results = []; - var spans = []; - var success = 0; - var replay = args.scanner.position; - ParseResult result; - - do { - result = parser._parse(args.increaseDepth()); - if (result.successful) { - success++; - if (result.value != null) { - results.add(result.value!); - } - replay = args.scanner.position; - } else if (backtrack) args.scanner.position = replay; - - if (result.span != null) { - spans.add(result.span!); - } - } while (result.successful); - - if (success < count) { - errors.addAll(result.errors); - errors.add( - SyntaxError( - severity, - tooFew, - result.span ?? args.scanner.emptySpan, - ), - ); - - if (backtrack) args.scanner.position = replay; - - return ParseResult>( - args.trampoline, args.scanner, this, false, errors); - } else if (success > count && exact) { - if (backtrack) args.scanner.position = replay; - - return ParseResult>(args.trampoline, args.scanner, this, false, [ - SyntaxError( - severity, - tooMany, - result.span ?? args.scanner.emptySpan, - ), - ]); - } - - var span = spans.reduce((a, b) => a.expand(b)); - return ParseResult>( - args.trampoline, - args.scanner, - this, - true, - [], - span: span, - value: results, - ); - } - - @override - void stringify(CodeBuffer buffer) { - var r = StringBuffer('{$count'); - if (!exact) r.write(','); - r.write('}'); - buffer - ..writeln('repeat($r) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/safe.dart b/packages/combinator/lib/src/combinator/safe.dart deleted file mode 100644 index a2542295..00000000 --- a/packages/combinator/lib/src/combinator/safe.dart +++ /dev/null @@ -1,47 +0,0 @@ -part of lex.src.combinator; - -class _Safe extends Parser { - final Parser parser; - final bool backtrack; - final String errorMessage; - final SyntaxErrorSeverity severity; - bool _triggered = false; - - _Safe(this.parser, this.backtrack, this.errorMessage, this.severity); - - @override - ParseResult __parse(ParseArgs args) { - var replay = args.scanner.position; - - try { - if (_triggered) throw Exception(); - return parser._parse(args.increaseDepth()); - } catch (_) { - _triggered = true; - if (backtrack) args.scanner.position = replay; - var errors = []; - - errors.add( - SyntaxError( - severity, - errorMessage, - args.scanner.lastSpan ?? args.scanner.emptySpan, - ), - ); - - return ParseResult(args.trampoline, args.scanner, this, false, errors); - } - } - - @override - void stringify(CodeBuffer buffer) { - var t = _triggered ? 'triggered' : 'not triggered'; - buffer - ..writeln('safe($t) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/to_list.dart b/packages/combinator/lib/src/combinator/to_list.dart deleted file mode 100644 index 320be1fc..00000000 --- a/packages/combinator/lib/src/combinator/to_list.dart +++ /dev/null @@ -1,41 +0,0 @@ -part of lex.src.combinator; - -class _ToList extends ListParser { - final Parser parser; - - _ToList(this.parser); - - @override - ParseResult> __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()); - - if (result.value is List) { - return (result as ParseResult>).change(parser: this); - } - - var values = []; - if (result.value != null) { - values.add(result.value!); - } - return ParseResult( - args.trampoline, - args.scanner, - this, - result.successful, - result.errors, - span: result.span, - value: values, - ); - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('to list (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/combinator/util.dart b/packages/combinator/lib/src/combinator/util.dart deleted file mode 100644 index cb5dcdc7..00000000 --- a/packages/combinator/lib/src/combinator/util.dart +++ /dev/null @@ -1,57 +0,0 @@ -part of lex.src.combinator; - -/// A typed parser that parses a sequence of 2 values of different types. -Parser> tuple2(Parser a, Parser b) { - return chain([a, b]).map((r) { - return Tuple2(r.value?[0] as A, r.value?[1] as B); - }); -} - -/// A typed parser that parses a sequence of 3 values of different types. -Parser> tuple3(Parser a, Parser b, Parser c) { - return chain([a, b, c]).map((r) { - return Tuple3(r.value?[0] as A, r.value?[1] as B, r.value?[2] as C); - }); -} - -/// A typed parser that parses a sequence of 4 values of different types. -Parser> tuple4( - Parser a, Parser b, Parser c, Parser d) { - return chain([a, b, c, d]).map((r) { - return Tuple4( - r.value?[0] as A, r.value?[1] as B, r.value?[2] as C, r.value?[3] as D); - }); -} - -/// A typed parser that parses a sequence of 5 values of different types. -Parser> tuple5( - Parser a, Parser b, Parser c, Parser d, Parser e) { - return chain([a, b, c, d, e]).map((r) { - return Tuple5(r.value?[0] as A, r.value?[1] as B, r.value?[2] as C, - r.value?[3] as D, r.value?[4] as E); - }); -} - -/// A typed parser that parses a sequence of 6 values of different types. -Parser> tuple6(Parser a, - Parser b, Parser c, Parser d, Parser e, Parser f) { - return chain([a, b, c, d, e, f]).map((r) { - return Tuple6(r.value?[0] as A, r.value?[1] as B, r.value?[2] as C, - r.value?[3] as D, r.value?[4] as E, r.value?[5] as F); - }); -} - -/// A typed parser that parses a sequence of 7 values of different types. -Parser> tuple7( - Parser a, - Parser b, - Parser c, - Parser d, - Parser e, - Parser f, - Parser g) { - return chain([a, b, c, d, e, f, g]).map((r) { - return Tuple7(r.value?[0] as A, r.value?[1] as B, r.value?[2] as C, - r.value?[3] as D, r.value?[4] as E, r.value?[5] as F, r.value?[6] as G); - }); -} diff --git a/packages/combinator/lib/src/combinator/value.dart b/packages/combinator/lib/src/combinator/value.dart deleted file mode 100644 index b0612073..00000000 --- a/packages/combinator/lib/src/combinator/value.dart +++ /dev/null @@ -1,25 +0,0 @@ -part of lex.src.combinator; - -class _Value extends Parser { - final Parser parser; - final T Function(ParseResult) f; - - _Value(this.parser, this.f); - - @override - ParseResult __parse(ParseArgs args) { - var result = parser._parse(args.increaseDepth()).change(parser: this); - return result.successful ? result.change(value: f(result)) : result; - } - - @override - void stringify(CodeBuffer buffer) { - buffer - ..writeln('set value($f) (') - ..indent(); - parser.stringify(buffer); - buffer - ..outdent() - ..writeln(')'); - } -} diff --git a/packages/combinator/lib/src/error.dart b/packages/combinator/lib/src/error.dart deleted file mode 100644 index 6c7b5f51..00000000 --- a/packages/combinator/lib/src/error.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:source_span/source_span.dart'; - -class SyntaxError implements Exception { - final SyntaxErrorSeverity severity; - final String? message; - final FileSpan? span; - String? _toolString; - - SyntaxError(this.severity, this.message, this.span); - - String? get toolString { - if (_toolString != null) return _toolString; - var type = severity == SyntaxErrorSeverity.warning ? 'warning' : 'error'; - return _toolString = '$type: ${span!.start.toolString}: $message'; - } -} - -enum SyntaxErrorSeverity { - warning, - error, - info, - hint, -} diff --git a/packages/combinator/pubspec.yaml b/packages/combinator/pubspec.yaml deleted file mode 100644 index 1f190118..00000000 --- a/packages/combinator/pubspec.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: angel3_combinator -version: 2.0.2 -description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more. -homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/combinator -environment: - sdk: '>=2.12.0 <3.0.0' -dependencies: - angel3_code_buffer: ^2.0.0 - matcher: ^0.12.10 - source_span: ^1.8.1 - string_scanner: ^1.1.0 - tuple: ^2.0.0 -dev_dependencies: - test: ^1.17.4 - pedantic: ^1.11.0 diff --git a/packages/combinator/test/all.dart b/packages/combinator/test/all.dart deleted file mode 100644 index 9022d5fa..00000000 --- a/packages/combinator/test/all.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:test/test.dart'; -import 'list_test.dart' as list; -import 'match_test.dart' as match; -import 'misc_test.dart' as misc; -import 'value_test.dart' as value; - -void main() { - group('list', list.main); - group('match', match.main); - group('value', value.main); - misc.main(); -} diff --git a/packages/combinator/test/common.dart b/packages/combinator/test/common.dart deleted file mode 100644 index 9ccc542b..00000000 --- a/packages/combinator/test/common.dart +++ /dev/null @@ -1,3 +0,0 @@ -import 'package:string_scanner/string_scanner.dart'; - -SpanScanner scan(String text) => SpanScanner(text); diff --git a/packages/combinator/test/list_test.dart b/packages/combinator/test/list_test.dart deleted file mode 100644 index 9489bbee..00000000 --- a/packages/combinator/test/list_test.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:test/test.dart'; -import 'common.dart'; - -void main() { - var number = chain([ - match(RegExp(r'[0-9]+')).value((r) => int.parse(r.span!.text)), - match(',').opt(), - ]).first().cast(); - - var numbers = number.plus(); - - test('sort', () { - var parser = numbers.sort((a, b) => a.compareTo(b)); - expect(parser.parse(scan('21,2,3,34,20')).value, [2, 3, 20, 21, 34]); - }); - test('reduce', () { - var parser = numbers.reduce((a, b) => a + b); - expect(parser.parse(scan('21,2,3,34,20')).value, 80); - expect(parser.parse(scan('not numbers')).value, isNull); - }); -} diff --git a/packages/combinator/test/match_test.dart b/packages/combinator/test/match_test.dart deleted file mode 100644 index b2a4bcc4..00000000 --- a/packages/combinator/test/match_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:test/test.dart'; -import 'common.dart'; - -void main() { - test('match string', () { - expect(match('hello').parse(scan('hello world')).successful, isTrue); - }); - test('match start only', () { - expect(match('hello').parse(scan('goodbye hello')).successful, isFalse); - }); - - test('fail if no match', () { - expect(match('hello').parse(scan('world')).successful, isFalse); - }); -} diff --git a/packages/combinator/test/misc_test.dart b/packages/combinator/test/misc_test.dart deleted file mode 100644 index aecdc1fb..00000000 --- a/packages/combinator/test/misc_test.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:matcher/matcher.dart'; -import 'package:test/test.dart'; -import 'common.dart'; - -void main() { - test('advance', () { - var scanner = scan('hello world'); - - // Casted -> dynamic just for the sake of coverage. - var parser = match('he').forward(2).castDynamic(); - parser.parse(scanner); - expect(scanner.position, 4); - }); - - test('change', () { - var parser = match('hello').change((r) => r.change(value: 23)); - expect(parser.parse(scan('helloworld')).value, 23); - }); - - test('check', () { - var parser = match(RegExp(r'[A-Za-z]+')) - .value((r) => r.span!.length) - .check(greaterThan(3)); - expect(parser.parse(scan('helloworld')).successful, isTrue); - expect(parser.parse(scan('yo')).successful, isFalse); - }); - - test('map', () { - var parser = match(RegExp(r'[A-Za-z]+')).map((r) => r.span!.length); - expect(parser.parse(scan('hello')).value, 5); - }); - - test('negate', () { - var parser = match('hello').negate(errorMessage: 'world'); - expect(parser.parse(scan('goodbye world')).successful, isTrue); - expect(parser.parse(scan('hello world')).successful, isFalse); - expect(parser.parse(scan('hello world')).errors.first.message, 'world'); - }); - - group('opt', () { - var single = match('hello').opt(backtrack: true); - var list = match('hel').then(match('lo')).opt(); - - test('succeeds if present', () { - expect(single.parse(scan('hello')).successful, isTrue); - expect(list.parse(scan('hello')).successful, isTrue); - }); - - test('succeeds if not present', () { - expect(single.parse(scan('goodbye')).successful, isTrue); - expect(list.parse(scan('goodbye')).successful, isTrue); - }); - - test('backtracks if not present', () { - for (var parser in [single, list]) { - var scanner = scan('goodbye'); - var pos = scanner.position; - parser.parse(scanner); - expect(scanner.position, pos); - } - }); - }); - - test('safe', () {}); -} diff --git a/packages/combinator/test/recursion_test.dart b/packages/combinator/test/recursion_test.dart deleted file mode 100644 index d91cebb9..00000000 --- a/packages/combinator/test/recursion_test.dart +++ /dev/null @@ -1,53 +0,0 @@ -void main() {} - -/* -void main() { - var number = match( RegExp(r'-?[0-9]+(\.[0-9]+)?')) - .map((r) => num.parse(r.span.text)); - - var term = reference(); - - var r = Recursion(); - - r.prefix = [number]; - - r.infix.addAll({ - match('*'): (l, r, _) => l * r, - match('/'): (l, r, _) => l / r, - match('+'): (l, r, _) => l + r, - match('-'): (l, r, _) => l - r, - - - match('-'): (l, r, _) => l - r, - match('+'): (l, r, _) => l + r, - match('/'): (l, r, _) => l / r, - match('*'): (l, r, _) => l * r, - - }); - - term.parser = r.precedence(0); - - num parse(String text) { - var scanner = SpanScanner(text); - var result = term.parse(scanner); - print(result.span.highlight()); - return result.value; - } - - test('prefix', () { - expect(parse('24'), 24); - }); - - test('infix', () { - expect(parse('12/6'), 2); - expect(parse('24+23'), 47); - expect(parse('24-23'), 1); - expect(parse('4*3'), 12); - }); - - test('precedence', () { - expect(parse('2+3*5*2'), 15); - //expect(parse('2+3+5-2*2'), 15); - }); -} -*/ diff --git a/packages/combinator/test/value_test.dart b/packages/combinator/test/value_test.dart deleted file mode 100644 index 7f2cb102..00000000 --- a/packages/combinator/test/value_test.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:angel3_combinator/angel3_combinator.dart'; -import 'package:test/test.dart'; -import 'common.dart'; - -void main() { - var parser = match('hello').value((r) => 'world'); - - test('sets value', () { - expect(parser.parse(scan('hello world')).value, 'world'); - }); - - test('no value if no match', () { - expect(parser.parse(scan('goodbye world')).value, isNull); - }); -} diff --git a/packages/pub_sub/.gitignore b/packages/pub_sub/.gitignore deleted file mode 100644 index 24d68312..00000000 --- a/packages/pub_sub/.gitignore +++ /dev/null @@ -1,71 +0,0 @@ -# See https://www.dartlang.org/tools/private-files.html - -# Files and directories created by pub -.dart_tool -.packages -.pub/ -build/ - -# If you're building an application, you may want to check-in your pubspec.lock -pubspec.lock - -# Directory created by dartdoc -# If you don't generate documentation locally you can remove this line. -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 -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: - -## VsCode -.vscode/ - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -.idea/ -/out/ -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties diff --git a/packages/user_agent/user_agent/.gitignore b/packages/user_agent/user_agent/.gitignore deleted file mode 100644 index 83f976e2..00000000 --- a/packages/user_agent/user_agent/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Files and directories created by pub -.packages -.pub/ -build/ -packages -# Remove the following pattern if you wish to check in your lock file -pubspec.lock - -# Files created by dart2js -*.dart.js -*.part.js -*.js.deps -*.js.map -*.info.json - -# Directory created by dartdoc -doc/api/ - -# JetBrains IDEs -.idea/ -*.iml -*.ipr -*.iws - -.dart_tool \ No newline at end of file diff --git a/packages/user_agent/user_agent/.travis.yml b/packages/user_agent/user_agent/.travis.yml deleted file mode 100644 index de2210c9..00000000 --- a/packages/user_agent/user_agent/.travis.yml +++ /dev/null @@ -1 +0,0 @@ -language: dart \ No newline at end of file diff --git a/packages/user_agent/user_agent/AUTHORS.md b/packages/user_agent/user_agent/AUTHORS.md deleted file mode 100644 index ac95ab58..00000000 --- a/packages/user_agent/user_agent/AUTHORS.md +++ /dev/null @@ -1,12 +0,0 @@ -Primary Authors -=============== - -* __[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. diff --git a/packages/user_agent/user_agent/CHANGELOG.md b/packages/user_agent/user_agent/CHANGELOG.md deleted file mode 100644 index 4a1e9ff4..00000000 --- a/packages/user_agent/user_agent/CHANGELOG.md +++ /dev/null @@ -1,17 +0,0 @@ -# Change Log - -## 3.0.1 - -* Updated to use non nullable results - -## 3.0.0 - -* Migrated to support Dart SDK 2.12.x NNBD - -## 2.0.0 - -* Dart 2 updates. - -## 0.0.1 - -* Initial version, created by Stagehand diff --git a/packages/user_agent/user_agent/LICENSE b/packages/user_agent/user_agent/LICENSE deleted file mode 100644 index b593ac86..00000000 --- a/packages/user_agent/user_agent/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 dukefirehawk.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/user_agent/user_agent/LICENSE.orig b/packages/user_agent/user_agent/LICENSE.orig deleted file mode 100644 index 05c76b04..00000000 --- a/packages/user_agent/user_agent/LICENSE.orig +++ /dev/null @@ -1,25 +0,0 @@ -BSD 2-Clause License - -Copyright (c) 2017, Tobe O -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/user_agent/user_agent/README.md b/packages/user_agent/user_agent/README.md index 8dce655d..aa6b9af3 100644 --- a/packages/user_agent/user_agent/README.md +++ b/packages/user_agent/user_agent/README.md @@ -1,28 +1,3 @@ # User Agent Analyzer -[![version](https://img.shields.io/badge/pub-v3.0.1-brightgreen)](https://pub.dartlang.org/packages/user_agent_analyzer) -[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) -[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) - -[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/user_agent/user_agent/LICENSE) - -**Forked from `user_agent` to support NNBD** - -A library to identify the type of devices and web browsers based on `User-Agent` string. - -Runs anywhere. - -```dart -void main() async { - app.get('/', (req, res) async { - var ua = UserAgent(req.headers.value('user-agent')); - - if (ua.isChrome) { - res.redirect('/upgrade-your-browser'); - return; - } else { - // ... - } - }); -} -``` +Moved to [`Belatuk Common Utilities`]() diff --git a/packages/user_agent/user_agent/analysis_options.yaml b/packages/user_agent/user_agent/analysis_options.yaml deleted file mode 100644 index c230cee7..00000000 --- a/packages/user_agent/user_agent/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:pedantic/analysis_options.yaml -analyzer: - strong-mode: - implicit-casts: false \ No newline at end of file diff --git a/packages/user_agent/user_agent/example/example.dart b/packages/user_agent/user_agent/example/example.dart deleted file mode 100644 index 3918e9d3..00000000 --- a/packages/user_agent/user_agent/example/example.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:user_agent_analyzer/user_agent_analyzer.dart'; - -void main() { - var ua = UserAgent( - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'); - print(ua.isChrome); -} diff --git a/packages/user_agent/user_agent/lib/user_agent_analyzer.dart b/packages/user_agent/user_agent/lib/user_agent_analyzer.dart deleted file mode 100644 index f86757f4..00000000 --- a/packages/user_agent/user_agent/lib/user_agent_analyzer.dart +++ /dev/null @@ -1,235 +0,0 @@ -library user_agent_analyzer; - -/// Utils for device detection. -class UserAgent { - bool _isChrome = false; - bool _isOpera = false; - bool _isIE = false; - bool _isFirefox = false; - bool _isWebKit = false; - String? _cachedCssPrefix; - String? _cachedPropertyPrefix; - - final String value, _lowerValue; - - static const List knownMobileUserAgentPrefixes = [ - 'w3c ', - 'w3c-', - 'acs-', - 'alav', - 'alca', - 'amoi', - 'audi', - 'avan', - 'benq', - 'bird', - 'blac', - 'blaz', - 'brew', - 'cell', - 'cldc', - 'cmd-', - 'dang', - 'doco', - 'eric', - 'hipt', - 'htc_', - 'inno', - 'ipaq', - 'ipod', - 'jigs', - 'kddi', - 'keji', - 'leno', - 'lg-c', - 'lg-d', - 'lg-g', - 'lge-', - 'lg/u', - 'maui', - 'maxo', - 'midp', - 'mits', - 'mmef', - 'mobi', - 'mot-', - 'moto', - 'mwbp', - 'nec-', - 'newt', - 'noki', - 'palm', - 'pana', - 'pant', - 'phil', - 'play', - 'port', - 'prox', - 'qwap', - 'sage', - 'sams', - 'sany', - 'sch-', - 'sec-', - 'send', - 'seri', - 'sgh-', - 'shar', - 'sie-', - 'siem', - 'smal', - 'smar', - 'sony', - 'sph-', - 'symb', - 't-mo', - 'teli', - 'tim-', - 'tosh', - 'tsm-', - 'upg1', - 'upsi', - 'vk-v', - 'voda', - 'wap-', - 'wapa', - 'wapi', - 'wapp', - 'wapr', - 'webc', - 'winw', - 'winw', - 'xda ', - 'xda-' - ]; - - static const List knownMobileUserAgentKeywords = [ - 'blackberry', - 'webos', - 'ipod', - 'lge vx', - 'midp', - 'maemo', - 'mmp', - 'mobile', - 'netfront', - 'hiptop', - 'nintendo DS', - 'novarra', - 'openweb', - 'opera mobi', - 'opera mini', - 'palm', - 'psp', - 'phone', - 'smartphone', - 'symbian', - 'up.browser', - 'up.link', - 'wap', - 'windows ce' - ]; - - static const List knownTabletUserAgentKeywords = [ - 'ipad', - 'playbook', - 'hp-tablet', - 'kindle' - ]; - - UserAgent(this.value) : _lowerValue = value.toLowerCase(); - - /// Determines if the user agent string contains the desired string. Case-insensitive. - bool contains(String needle) => _lowerValue.contains(needle.toLowerCase()); - - bool get isDesktop => isMacOS || (!isMobile && !isTablet); - - bool get isTablet => knownTabletUserAgentKeywords.any(contains); - - bool get isMobile => knownMobileUserAgentKeywords.any(contains); - - bool get isMacOS => contains('Macintosh') || contains('Mac OS X'); - - bool get isSafari => contains('Safari'); - - bool get isAndroid => contains('android'); - - bool get isAndroidPhone => contains('android') && contains('mobile'); - - bool get isAndroidTablet => contains('android') && !contains('mobile'); - - bool get isWindows => contains('windows'); - - bool get isWindowsPhone => isWindows && contains('phone'); - - bool get isWindowsTablet => isWindows && contains('touch'); - - bool get isBlackberry => - contains('blackberry') || contains('bb10') || contains('rim'); - - bool get isBlackberryPhone => isBlackberry && !contains('tablet'); - - bool get isBlackberryTablet => isBlackberry && contains('tablet'); - - /// Determines if the current device is running Chrome. - bool get isChrome { - _isChrome = value.contains('Chrome', 0); - return _isChrome; - } - - /// Determines if the current device is running Opera. - bool get isOpera { - _isOpera = value.contains('Opera', 0); - return _isOpera; - } - - /// Determines if the current device is running Internet Explorer. - bool get isIE { - _isIE = !isOpera && value.contains('Trident/', 0); - return _isIE; - } - - /// Determines if the current device is running Firefox. - bool get isFirefox { - _isFirefox = value.contains('Firefox', 0); - return _isFirefox; - } - - /// Determines if the current device is running WebKit. - bool get isWebKit { - _isWebKit = !isOpera && value.contains('WebKit', 0); - return _isWebKit; - } - - /// Gets the CSS property prefix for the current platform. - String get cssPrefix { - var prefix = _cachedCssPrefix; - if (prefix != null) return prefix; - if (isFirefox) { - prefix = '-moz-'; - } else if (isIE) { - prefix = '-ms-'; - } else if (isOpera) { - prefix = '-o-'; - } else { - prefix = '-webkit-'; - } - return _cachedCssPrefix = prefix; - } - - /// Prefix as used for JS property names. - String get propertyPrefix { - var prefix = _cachedPropertyPrefix; - if (prefix != null) return prefix; - if (isFirefox) { - prefix = 'moz'; - } else if (isIE) { - prefix = 'ms'; - } else if (isOpera) { - prefix = 'o'; - } else { - prefix = 'webkit'; - } - return _cachedPropertyPrefix = prefix; - } -} diff --git a/packages/user_agent/user_agent/pubspec.yaml b/packages/user_agent/user_agent/pubspec.yaml deleted file mode 100644 index 79e17f8d..00000000 --- a/packages/user_agent/user_agent/pubspec.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: user_agent_analyzer -version: 3.0.1 -description: A library to identify the type of devices and web browsers based on User-Agent string. -homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/user_agent/user_agent -environment: - sdk: '>=2.12.0 <3.0.0' -dev_dependencies: - test: ^1.17.8 - pedantic: ^1.11.1 diff --git a/packages/user_agent/user_agent/test/user_agent_test.dart b/packages/user_agent/user_agent/test/user_agent_test.dart deleted file mode 100644 index 4721765c..00000000 --- a/packages/user_agent/user_agent/test/user_agent_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2017, thosakwe. All rights reserved. Use of this source code -// is governed by a BSD-style license that can be found in the LICENSE file. - -import 'package:user_agent_analyzer/user_agent_analyzer.dart'; -import 'package:test/test.dart'; - -void main() { - test('chrome', () { - var ua = UserAgent( - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'); - expect([ua.isChrome, ua.isWebKit, ua.isSafari, ua.isDesktop, ua.isMacOS], - everyElement(isTrue)); - expect([ua.isFirefox, ua.isIE, ua.isOpera, ua.isMobile, ua.isTablet], - everyElement(isFalse)); - expect([ - ua.isAndroid, - ua.isAndroidPhone, - ua.isAndroidTablet, - ua.isBlackberry, - ua.isBlackberryPhone, - ua.isBlackberryTablet, - ua.isWindows, - ua.isWindowsPhone, - ua.isWindowsTablet - ], everyElement(isFalse)); - - expect(ua.cssPrefix, equals('-webkit-')); - expect(ua.propertyPrefix, equals('webkit')); - }); -}