Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(857)

Unified Diff: packages/petitparser/lib/src/petitparser/composite.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packages/petitparser/lib/src/petitparser/composite.dart
diff --git a/packages/petitparser/lib/src/petitparser/composite.dart b/packages/petitparser/lib/src/petitparser/composite.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b7e8583bf40716a0da2a2a0c949416e4255d502d
--- /dev/null
+++ b/packages/petitparser/lib/src/petitparser/composite.dart
@@ -0,0 +1,167 @@
+part of petitparser;
+
+/// Helper to compose complex grammars from various primitive parsers.
+///
+/// Note, this class is deprecated in favor of [GrammarDefinition] that provides
+/// a more flexible way to define composite parsers.
+///
+/// To create a new composite grammar subclass [CompositeParser]. Override
+/// the method [initialize] and for every production call [def] giving the
+/// production a name. The start production must be named 'start'. To refer
+/// to other productions (forward and backward) use [ref].
+///
+/// Consider the following example to parse a list of numbers:
+///
+/// class NumberListGrammar extends CompositeParser {
+/// void initialize() {
+/// def('start', ref('list').end());
+/// def('list', ref('element').separatedBy(char(','),
+/// includeSeparators: false));
+/// def('element', digit().plus().flatten());
+/// }
+/// }
+///
+/// You might want to create future subclasses of your composite grammar
+/// to redefine the grammar or attach custom actions. In such a subclass
+/// override the method [initialize] again and call super. Then use
+/// [redef] to redefine an existing production, and [action] to attach an
+/// action to an existing production.
+///
+/// Consider the following example that attaches a production action and
+/// converts the digits to actual numbers:
+///
+/// class NumberListParser extends NumberListGrammar {
+/// void initialize() {
+/// action('element', (value) => int.parse(value));
+/// }
+/// }
+@deprecated
+abstract class CompositeParser extends DelegateParser {
+ bool _completed = false;
+ final Map<String, Parser> _defined = new Map();
+ final Map<String, SettableParser> _undefined = new Map();
+
+ CompositeParser() : super(failure('Not initalized production: start')) {
+ initialize();
+ _complete();
+ }
+
+ /// Initializes the composite grammar.
+ void initialize();
+
+ /// Internal method to complete the grammar.
+ void _complete() {
+ _delegate = ref('start');
+ _undefined.forEach((name, parser) {
+ if (!_defined.containsKey(name)) {
+ throw new UndefinedProductionError(name);
+ }
+ parser.set(_defined[name]);
+ });
+ _undefined.clear();
+ _completed = true;
+ _delegate = ref('start');
+ }
+
+ /// Returns a reference to a production with a [name].
+ ///
+ /// This method works during initialization and after completion of the
+ /// initialization. During the initialization it returns delegate parsers
+ /// that are eventually replaced by the real parsers. Afterwards it
+ /// returns the defined parser (mostly useful for testing).
+ Parser ref(String name) {
+ if (_completed) {
+ if (_defined.containsKey(name)) {
+ return _defined[name];
+ } else {
+ throw new UndefinedProductionError(name);
+ }
+ } else {
+ return _undefined.putIfAbsent(name, () {
+ return failure('Not initalized production: $name').settable();
+ });
+ }
+ }
+
+ /// Convenience operator returning a reference to a production with
+ /// a [name]. See [CompositeParser.ref] for details.
+ Parser operator [](String name) => ref(name);
+
+ /// Defines a production with a [name] and a [parser]. Only call this method
+ /// from [initialize].
+ ///
+ /// The following example defines a list production that consumes
+ /// several elements separated by a comma.
+ ///
+ /// def('list', ref('element').separatedBy(char(',')));
+ void def(String name, Parser parser) {
+ if (_completed) {
+ throw new CompletedParserError();
+ } else if (_defined.containsKey(name)) {
+ throw new RedefinedProductionError(name);
+ } else {
+ _defined[name] = parser;
+ }
+ }
+
+ /// Redefines an existing production with a [name] and a [replacement]
+ /// parser or function producing a new parser. The code raises an
+ /// [UndefinedProductionError] if [name] is an undefined production. Only call
+ /// this method from [initialize].
+ ///
+ /// The following example redefines the previously defined list production
+ /// by making it optional:
+ ///
+ /// redef('list', (parser) => parser.optional());
+ void redef(String name, replacement) {
+ if (_completed) {
+ throw new CompletedParserError();
+ } else if (!_defined.containsKey(name)) {
+ throw new UndefinedProductionError(name);
+ } else {
+ _defined[name] =
+ replacement is Parser ? replacement : replacement(_defined[name]);
+ }
+ }
+
+ /// Attaches an action [function] to an existing production [name]. The code
+ /// raises an [UndefinedProductionError] if [name] is an undefined production.
+ /// Only call this method from [initialize].
+ ///
+ /// The following example attaches an action returning the size of list of
+ /// the previously defined list production:
+ ///
+ /// action('list', (list) => list.length);
+ void action(String name, Function function) {
+ redef(name, (parser) => parser.map(function));
+ }
+}
+
+/// Error raised when somebody tries to modify a [CompositeParser] outside
+/// the [CompositeParser.initialize] method.
+class CompletedParserError extends Error {
+ CompletedParserError();
+
+ @override
+ String toString() => 'Completed parser';
+}
+
+/// Error raised when an undefined production is accessed.
+class UndefinedProductionError extends Error {
+ final String name;
+
+ UndefinedProductionError(this.name);
+
+ @override
+ String toString() => 'Undefined production: $name';
+}
+
+/// Error raised when a production is accidentally redefined.
+class RedefinedProductionError extends Error {
+ final String name;
+
+ RedefinedProductionError(this.name);
+
+ @override
+ String toString() => 'Redefined production: $name';
+}
« no previous file with comments | « packages/petitparser/lib/src/petitparser/combinators.dart ('k') | packages/petitparser/lib/src/petitparser/context.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698