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

Side by Side Diff: petitparser/lib/src/core/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 unified diff | Download patch
« no previous file with comments | « petitparser/lib/src/core/combinators.dart ('k') | petitparser/lib/src/core/context.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 part of petitparser;
2
3 /**
4 * Helper to compose complex grammars from various primitive parsers.
5 *
6 * Note, this class is deprecated in favor of [GrammarDefinition] that provides
7 * a more flexible way to define composite parsers.
8 *
9 * To create a new composite grammar subclass [CompositeParser]. Override
10 * the method [initialize] and for every production call [def] giving the
11 * production a name. The start production must be named 'start'. To refer
12 * to other productions (forward and backward) use [ref].
13 *
14 * Consider the following example to parse a list of numbers:
15 *
16 * class NumberListGrammar extends CompositeParser {
17 * void initialize() {
18 * def('start', ref('list').end());
19 * def('list', ref('element').separatedBy(char(','),
20 * includeSeparators: false));
21 * def('element', digit().plus().flatten());
22 * }
23 * }
24 *
25 * You might want to create future subclasses of your composite grammar
26 * to redefine the grammar or attach custom actions. In such a subclass
27 * override the method [initialize] again and call super. Then use
28 * [redef] to redefine an existing production, and [action] to attach an
29 * action to an existing production.
30 *
31 * Consider the following example that attaches a production action and
32 * converts the digits to actual numbers:
33 *
34 * class NumberListParser extends NumberListGrammar {
35 * void initialize() {
36 * action('element', (value) => int.parse(value));
37 * }
38 * }
39 */
40 @deprecated
41 abstract class CompositeParser extends DelegateParser {
42 bool _completed = false;
43 final Map<String, Parser> _defined = new Map();
44 final Map<String, SettableParser> _undefined = new Map();
45
46 CompositeParser() : super(failure('Not initalized production: start')) {
47 initialize();
48 _complete();
49 }
50
51 /**
52 * Initializes the composite grammar.
53 */
54 void initialize();
55
56 /**
57 * Internal method to complete the grammar.
58 */
59 void _complete() {
60 _delegate = ref('start');
61 _undefined.forEach((name, parser) {
62 if (!_defined.containsKey(name)) {
63 throw new UndefinedProductionError(name);
64 }
65 parser.set(_defined[name]);
66 });
67 _undefined.clear();
68 _completed = true;
69 _delegate = ref('start');
70 }
71
72 /**
73 * Returns a reference to a production with a [name].
74 *
75 * This method works during initialization and after completion of the
76 * initialization. During the initialization it returns delegate parsers
77 * that are eventually replaced by the real parsers. Afterwards it
78 * returns the defined parser (mostly useful for testing).
79 */
80 Parser ref(String name) {
81 if (_completed) {
82 if (_defined.containsKey(name)) {
83 return _defined[name];
84 } else {
85 throw new UndefinedProductionError(name);
86 }
87 } else {
88 return _undefined.putIfAbsent(name, () {
89 return failure('Not initalized production: $name').settable();
90 });
91 }
92 }
93
94 /**
95 * Convenience operator returning a reference to a production with
96 * a [name]. See [CompositeParser.ref] for details.
97 */
98 Parser operator [](String name) => ref(name);
99
100 /**
101 * Defines a production with a [name] and a [parser]. Only call this method
102 * from [initialize].
103 *
104 * The following example defines a list production that consumes
105 * several elements separated by a comma.
106 *
107 * def('list', ref('element').separatedBy(char(',')));
108 */
109 void def(String name, Parser parser) {
110 if (_completed) {
111 throw new CompletedParserError();
112 } else if (_defined.containsKey(name)) {
113 throw new RedefinedProductionError(name);
114 } else {
115 _defined[name] = parser;
116 }
117 }
118
119 /**
120 * Redefines an existing production with a [name] and a [replacement]
121 * parser or function producing a new parser. The code raises an
122 * [UndefinedProductionError] if [name] is an undefined production. Only call
123 * this method from [initialize].
124 *
125 * The following example redefines the previously defined list production
126 * by making it optional:
127 *
128 * redef('list', (parser) => parser.optional());
129 */
130 void redef(String name, replacement) {
131 if (_completed) {
132 throw new CompletedParserError();
133 } else if (!_defined.containsKey(name)) {
134 throw new UndefinedProductionError(name);
135 } else {
136 _defined[name] =
137 replacement is Parser ? replacement : replacement(_defined[name]);
138 }
139 }
140
141 /**
142 * Attaches an action [function] to an existing production [name]. The code
143 * raises an [UndefinedProductionError] if [name] is an undefined production.
144 * Only call this method from [initialize].
145 *
146 * The following example attaches an action returning the size of list of
147 * the previously defined list production:
148 *
149 * action('list', (list) => list.length);
150 */
151 void action(String name, Function function) {
152 redef(name, (parser) => parser.map(function));
153 }
154 }
155
156 /**
157 * Error raised when somebody tries to modify a [CompositeParser] outside
158 * the [CompositeParser.initialize] method.
159 */
160 class CompletedParserError extends Error {
161 CompletedParserError();
162
163 @override
164 String toString() => 'Completed parser';
165 }
166
167 /**
168 * Error raised when an undefined production is accessed.
169 */
170 class UndefinedProductionError extends Error {
171 final String name;
172
173 UndefinedProductionError(this.name);
174
175 @override
176 String toString() => 'Undefined production: $name';
177 }
178
179 /**
180 * Error raised when a production is accidentally redefined.
181 */
182 class RedefinedProductionError extends Error {
183 final String name;
184
185 RedefinedProductionError(this.name);
186
187 @override
188 String toString() => 'Redefined production: $name';
189 }
OLDNEW
« no previous file with comments | « petitparser/lib/src/core/combinators.dart ('k') | petitparser/lib/src/core/context.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698