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

Side by Side Diff: pkg/fletchc/lib/src/hub/sentence_parser.dart

Issue 1659163007: Rename fletch -> dartino (Closed) Base URL: https://github.com/dartino/sdk.git@master
Patch Set: address comments Created 4 years, 10 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 | « pkg/fletchc/lib/src/hub/hub_main.dart ('k') | pkg/fletchc/lib/src/hub/session_manager.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 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 library fletchc.hub.sentence_parser;
6
7 import 'dart:convert' show
8 JSON;
9
10 import '../verbs/actions.dart' show
11 Action,
12 commonActions,
13 uncommonActions;
14
15 import '../verbs/infrastructure.dart' show
16 AnalyzedSentence,
17 DiagnosticKind,
18 throwFatalError;
19
20 Sentence parseSentence(
21 Iterable<String> arguments,
22 {bool includesProgramName}) {
23 SentenceParser parser =
24 new SentenceParser(arguments, includesProgramName == true);
25 return parser.parseSentence();
26 }
27
28 class SentenceParser {
29 final String version;
30 final String programName;
31 final String shortProgramName;
32 final String currentDirectory;
33 Words tokens;
34
35 SentenceParser(Iterable<String> tokens, bool includesProgramName)
36 : version = includesProgramName ? tokens.first : null,
37 currentDirectory = includesProgramName ? tokens.skip(1).first : null,
38 programName = includesProgramName ? tokens.skip(2).first : null,
39 shortProgramName = includesProgramName ? tokens.skip(3).first : null,
40 tokens = new Words(tokens.skip(includesProgramName ? 4 : 0));
41
42 Sentence parseSentence() {
43 Verb verb;
44 if (!tokens.isAtEof) {
45 verb = parseVerb();
46 } else {
47 verb = new Verb("help", commonActions["help"]);
48 }
49 List<Preposition> prepositions = <Preposition>[];
50 List<Target> targets = <Target>[];
51 while (!tokens.isAtEof) {
52 Preposition preposition = parsePrepositionOpt();
53 if (preposition != null) {
54 prepositions.add(preposition);
55 continue;
56 }
57 Target target = parseTargetOpt();
58 if (target != null) {
59 targets.add(target);
60 continue;
61 }
62 break;
63 }
64 List<String> trailing = <String>[];
65 while (!tokens.isAtEof) {
66 trailing.add(tokens.current);
67 tokens.consume();
68 }
69 if (trailing.isEmpty) {
70 trailing = null;
71 }
72 return new Sentence(
73 verb, prepositions, targets, trailing,
74 version, currentDirectory, programName,
75 // TODO(ahe): Get rid of the following argument:
76 tokens.originalInput.skip(2).toList());
77 }
78
79 Verb parseVerb() {
80 String name = tokens.current;
81 Action action = commonActions[name];
82 if (action != null) {
83 tokens.consume();
84 return new Verb(name, action);
85 }
86 action = uncommonActions[name];
87 if (action != null) {
88 tokens.consume();
89 return new Verb(name, action);
90 }
91 return new ErrorVerb(name);
92 }
93
94 Preposition parsePrepositionOpt() {
95 // TODO(ahe): toLowerCase()?
96 String word = tokens.current;
97 Preposition makePreposition(PrepositionKind kind) {
98 tokens.consume();
99 Target target = tokens.isAtEof ? null : parseTarget();
100 return new Preposition(kind, target);
101 }
102 switch (word) {
103 case "with":
104 return makePreposition(PrepositionKind.WITH);
105
106 case "in":
107 return makePreposition(PrepositionKind.IN);
108
109 case "to":
110 return makePreposition(PrepositionKind.TO);
111
112
113 default:
114 return null;
115 }
116 }
117
118 // @private_to.instance
119 Target internalParseTarget() {
120 // TODO(ahe): toLowerCase()?
121 String word = tokens.current;
122
123 NamedTarget makeNamedTarget(TargetKind kind) {
124 tokens.consume();
125 return new NamedTarget(kind, parseName());
126 }
127
128 Target makeTarget(TargetKind kind) {
129 tokens.consume();
130 return new Target(kind);
131 }
132
133 if (looksLikeAUri(word)) {
134 return new NamedTarget(TargetKind.FILE, parseName());
135 }
136
137 switch (word) {
138 case "session":
139 return makeNamedTarget(TargetKind.SESSION);
140
141 case "class":
142 return makeNamedTarget(TargetKind.CLASS);
143
144 case "method":
145 return makeNamedTarget(TargetKind.METHOD);
146
147 case "file":
148 return makeNamedTarget(TargetKind.FILE);
149
150 case "agent":
151 return makeTarget(TargetKind.AGENT);
152
153 case "settings":
154 return makeTarget(TargetKind.SETTINGS);
155
156 case "tcp_socket":
157 return makeNamedTarget(TargetKind.TCP_SOCKET);
158
159 case "sessions":
160 return makeTarget(TargetKind.SESSIONS);
161
162 case "classes":
163 return makeTarget(TargetKind.CLASSES);
164
165 case "methods":
166 return makeTarget(TargetKind.METHODS);
167
168 case "files":
169 return makeTarget(TargetKind.FILES);
170
171 case "all":
172 return makeTarget(TargetKind.ALL);
173
174 case "run-to-main":
175 return makeTarget(TargetKind.RUN_TO_MAIN);
176
177 case "backtrace":
178 return makeTarget(TargetKind.BACKTRACE);
179
180 case "continue":
181 return makeTarget(TargetKind.CONTINUE);
182
183 case "break":
184 return makeNamedTarget(TargetKind.BREAK);
185
186 case "list":
187 return makeTarget(TargetKind.LIST);
188
189 case "disasm":
190 return makeTarget(TargetKind.DISASM);
191
192 case "frame":
193 return makeNamedTarget(TargetKind.FRAME);
194
195 case "delete-breakpoint":
196 return makeNamedTarget(TargetKind.DELETE_BREAKPOINT);
197
198 case "list-breakpoints":
199 return makeTarget(TargetKind.LIST_BREAKPOINTS);
200
201 case "step":
202 return makeTarget(TargetKind.STEP);
203
204 case "step-over":
205 return makeTarget(TargetKind.STEP_OVER);
206
207 case "fibers":
208 return makeTarget(TargetKind.FIBERS);
209
210 case "finish":
211 return makeTarget(TargetKind.FINISH);
212
213 case "restart":
214 return makeTarget(TargetKind.RESTART);
215
216 case "step-bytecode":
217 return makeTarget(TargetKind.STEP_BYTECODE);
218
219 case "step-over-bytecode":
220 return makeTarget(TargetKind.STEP_OVER_BYTECODE);
221
222 case "print":
223 return makeNamedTarget(TargetKind.PRINT);
224
225 case "print-all":
226 return makeTarget(TargetKind.PRINT_ALL);
227
228 case "toggle":
229 return makeNamedTarget(TargetKind.TOGGLE);
230
231 case "help":
232 return makeTarget(TargetKind.HELP);
233
234 case "log":
235 return makeTarget(TargetKind.LOG);
236
237 case "devices":
238 return makeTarget(TargetKind.DEVICES);
239
240 case "apply":
241 return makeTarget(TargetKind.APPLY);
242
243 default:
244 return new ErrorTarget(DiagnosticKind.expectedTargetButGot, word);
245 }
246 }
247
248 Target parseTargetOpt() {
249 Target target = internalParseTarget();
250 return target is ErrorTarget ? null : target;
251 }
252
253 Target parseTarget() {
254 Target target = internalParseTarget();
255 if (target is ErrorTarget) {
256 tokens.consume();
257 }
258 return target;
259 }
260
261 String parseName() {
262 // TODO(ahe): Rename this method? It doesn't necessarily parse a name, just
263 // whatever is the next word.
264 String name = tokens.current;
265 tokens.consume();
266 return name;
267 }
268
269 /// Returns true if [word] looks like it is a (relative) URI.
270 bool looksLikeAUri(String word) {
271 return
272 word != null &&
273 !word.startsWith("-") &&
274 word.contains(".");
275 }
276 }
277
278 String quoteString(String string) => JSON.encode(string);
279
280 class Words {
281 final Iterable<String> originalInput;
282
283 final Iterator<String> iterator;
284
285 // @private_to.instance
286 bool internalIsAtEof;
287
288 // @private_to.instance
289 int internalPosition = 0;
290
291 Words(Iterable<String> input)
292 : this.internal(input, input.iterator);
293
294 Words.internal(this.originalInput, Iterator<String> iterator)
295 : iterator = iterator,
296 internalIsAtEof = !iterator.moveNext();
297
298 bool get isAtEof => internalIsAtEof;
299
300 int get position => internalPosition;
301
302 String get current => iterator.current;
303
304 void consume() {
305 internalIsAtEof = !iterator.moveNext();
306 if (!isAtEof) {
307 internalPosition++;
308 }
309 }
310 }
311
312 class Verb {
313 final String name;
314 final Action action;
315
316 const Verb(this.name, this.action);
317
318 bool get isErroneous => false;
319
320 String toString() => "Verb(${quoteString(name)})";
321 }
322
323 class ErrorVerb implements Verb {
324 final String name;
325
326 const ErrorVerb(this.name);
327
328 bool get isErroneous => true;
329
330 Action get action {
331 throwFatalError(DiagnosticKind.unknownAction, userInput: name);
332 }
333 }
334
335 class Preposition {
336 final PrepositionKind kind;
337 final Target target;
338
339 const Preposition(this.kind, this.target);
340
341 String toString() => "Preposition($kind, $target)";
342 }
343
344 enum PrepositionKind {
345 WITH,
346 IN,
347 TO,
348 }
349
350 class Target {
351 final TargetKind kind;
352
353 const Target(this.kind);
354
355 bool get isErroneous => false;
356
357 String toString() => "Target($kind)";
358 }
359
360 enum TargetKind {
361 AGENT,
362 ALL,
363 APPLY,
364 BACKTRACE,
365 BREAK,
366 CLASS,
367 CLASSES,
368 CONTINUE,
369 DELETE_BREAKPOINT,
370 DEVICES,
371 DISASM,
372 FIBERS,
373 FILE,
374 FILES,
375 FINISH,
376 FRAME,
377 HELP,
378 LIST,
379 LIST_BREAKPOINTS,
380 LOG,
381 METHOD,
382 METHODS,
383 PRINT,
384 PRINT_ALL,
385 RESTART,
386 RUN_TO_MAIN,
387 SESSION,
388 SESSIONS,
389 SETTINGS,
390 STEP,
391 STEP_BYTECODE,
392 STEP_OVER,
393 STEP_OVER_BYTECODE,
394 TCP_SOCKET,
395 TOGGLE,
396 }
397
398 class NamedTarget extends Target {
399 final String name;
400
401 const NamedTarget(TargetKind kind, this.name)
402 : super(kind);
403
404 String toString() {
405 return "NamedTarget($kind, ${quoteString(name)})";
406 }
407 }
408
409 class ErrorTarget extends Target {
410 final DiagnosticKind errorKind;
411 final String userInput;
412
413 const ErrorTarget(this.errorKind, this.userInput)
414 : super(null);
415
416 bool get isErroneous => true;
417
418 String toString() => "ErrorTarget($errorKind, ${quoteString(userInput)})";
419 }
420
421 /// A sentence is a written command to fletch. Normally, this command is
422 /// written on the command-line and should be easy to write without having
423 /// getting into conflict with Unix shell command line parsing.
424 ///
425 /// An example sentence is:
426 /// `create class MyClass in session MySession`
427 ///
428 /// In this example, `create` is a [Verb], `class MyClass` is a [Target], and
429 /// `in session MySession` is a [Preposition].
430 class Sentence {
431 /// For example, `create`.
432 final Verb verb;
433
434 /// For example, `in session MySession`
435 final List<Preposition> prepositions;
436
437 /// For example, `class MyClass`
438 final List<Target> targets;
439
440 /// Any tokens found after this sentence.
441 final List<String> trailing;
442
443 /// The current directory of the C++ client.
444 final String currentDirectory;
445
446 // TODO(ahe): Get rid of this.
447 final String programName;
448
449 final String version;
450
451 // TODO(ahe): Get rid of this.
452 final List<String> arguments;
453
454 const Sentence(
455 this.verb,
456 this.prepositions,
457 this.targets,
458 this.trailing,
459 this.version,
460 this.currentDirectory,
461 this.programName,
462 this.arguments);
463
464 String toString() => "Sentence($verb, $prepositions, $targets)";
465 }
OLDNEW
« no previous file with comments | « pkg/fletchc/lib/src/hub/hub_main.dart ('k') | pkg/fletchc/lib/src/hub/session_manager.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698