PageRenderTime 52ms CodeModel.GetById 17ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 1ms

/tools/dspec/parser.d

http://github.com/wilkie/djehuty
D | 623 lines | 465 code | 127 blank | 31 comment | 101 complexity | b54baff8c15bc10d3e5b32a9e205454b MD5 | raw file
  1module parser;
  2
  3import djehuty;
  4
  5import io.console;
  6import io.directory;
  7
  8import filelist;
  9import output;
 10
 11import feeder;
 12import parseunit;
 13import ast;
 14
 15class Parser {
 16	bool parseFiles(string inputPath, string outputPath, FileList files) {
 17		if (inputPath[$-1] != '/') {
 18			inputPath ~= '/';
 19		}
 20		if (outputPath[$-1] != '/') {
 21			outputPath ~= '/';
 22		}
 23
 24		foreach(f; files) {
 25			// Create directories as needed in outputPath
 26			auto dir = Directory.openOrCreate(outputPath);
 27			string[] path = f[inputPath.length..$].split('/');
 28			string filepath = outputPath;
 29			foreach(directory; path[0..$-1]) {
 30				filepath ~= "/" ~ directory;
 31				dir = Directory.openOrCreate(filepath);
 32			}
 33			output = new Output(outputPath ~ f[inputPath.length..$-1]);
 34			if (!(parseFile(f))) {
 35				return false;
 36			}
 37		}
 38
 39		output.finalizeOutput();
 40
 41		return true;
 42	}
 43
 44protected:
 45
 46	Output output;
 47
 48	bool parseFile(string path) {
 49		Feeder feeder = new Feeder(path);
 50
 51		// write out intentions
 52		//Console.putln("Parsing ... ", path.array);
 53
 54		parseUnit = new ParseDSpec();
 55
 56		parseUnit.attachFeeder(feeder);
 57
 58		//Console.putln("Begin Parsing ... ", path.array);
 59
 60		AST finished = parseUnit.parse();
 61
 62		//Console.putln("Done Parsing");
 63
 64		output.work(finished, path);
 65
 66		return true;
 67	}
 68
 69	// parsing
 70
 71	ParseUnit parseUnit;
 72}
 73
 74bool isDelimiter(string s) {
 75	if (s.length > 1 || s.length == 0) {
 76		return false;
 77	}
 78
 79	foreach(cmp; delims) {
 80		if (cmp == s[0]) {
 81			return true;
 82		}
 83	}
 84
 85	return false;
 86}
 87
 88class ParseDSpec : ParseUnit {
 89	this() {
 90		// hook for describe section
 91		registerToken("describe", &parseDescribe);
 92		registerToken("import", &parseImport);
 93		registerToken("module", &parseModule);
 94
 95		// hook for comments
 96		//registerToken(...)
 97	}
 98
 99	void parseDescribe() {
100		AST ast = newParseUnit(new ParseDescribe());
101		progressTree(ast);
102	}
103
104	void parseImport() {
105		AST ast = newParseUnit(new ParseImport());
106		progressTree(ast);
107	}
108
109	void parseModule() {
110		AST ast = newParseUnit(new ParseModule());
111		progressTree(ast);
112	}
113}
114
115class ParseModule : ParseUnit {
116	string mod;
117
118	this() {
119		registerToken(";", &parseSemicolon);
120		mod = "";
121	}
122
123	void parseSemicolon() {
124		AST ast = new AST(null, null);
125		ast.value = mod;
126		progressTree(ast);
127
128		done();
129	}
130
131	void parseDefault() {
132		if (currentToken != "module") {
133			mod ~= currentToken;
134		}
135	}
136}
137
138class ParseImport : ParseUnit {
139	string mod;
140
141	this() {
142		registerToken(";", &parseSemicolon);
143		mod = "";
144	}
145
146	void parseSemicolon() {
147		AST ast = new AST(null, null);
148		ast.value = mod;
149		progressTree(ast);
150
151		done();
152	}
153
154	void parseDefault() {
155		if (currentToken != "import") {
156			mod ~= currentToken;
157		}
158	}
159}
160
161class ParseDescribe : ParseUnit {
162	this() {
163		working = "";
164
165		registerToken("describe", &parseDescribe);
166		registerToken("it", &parseIt);
167		registerToken("done", &parseDone);
168
169		registerToken("{", &parseLeft);
170		registerToken("}", &parseRight);
171	}
172
173protected:
174
175	bool foundDescribe = false;
176	bool foundName = false;
177	int foundLeft = 0;
178
179	string name;
180
181	string working;
182
183	void parseDescribe() {
184		if (foundDescribe) {
185			if (working.length > 0) {
186				AST ast = new AST(null, null);
187				ast.value = working;
188				progressTree(ast);
189
190				working = "";
191			}
192			AST section;
193			section = newParseUnit(new ParseDescribeSection());
194
195			progressTree(section);
196		}
197		else {
198			foundDescribe = true;
199		}
200	}
201
202	void parseIt() {
203		if (working.length > 0) {
204			AST ast = new AST(null, null);
205			ast.value = working;
206			progressTree(ast);
207
208			working = "";
209		}
210
211		AST section;
212		section = newParseUnit(new ParseIt());
213
214		progressTree(section);
215	}
216
217	void parseDone() {
218		if (working.length > 0) {
219			AST ast = new AST(null, null);
220			ast.value = working;
221			progressTree(ast);
222
223			working = "";
224		}
225
226		AST section;
227		section = newParseUnit(new ParseDone());
228
229		progressTree(section);
230	}
231
232	void parseLeft() {
233		foundLeft++;
234		if (foundLeft > 1) {
235			working ~= currentToken;
236		}
237	}
238
239	void parseRight() {
240		foundLeft--;
241		if (foundLeft == 0) {
242			// done
243			if (working.length > 0) {
244				AST ast = new AST(null, null);
245				ast.value = working;
246				progressTree(ast);
247
248				working = "";
249			}
250			done();
251		}
252		else {
253			working ~= currentToken;
254		}
255	}
256
257	void parseDefault() {
258		if (foundDescribe && !foundName && !foundLeft && !isDelimiter(currentToken)) {
259			foundName = true;
260			name = currentToken;
261			//Console.putln("Section: ", name.array);
262
263			AST meta = new AST(null, new AST(null, null));
264			meta.name = "Identifier";
265			meta.right.value = name;
266			progressTree(meta);
267		}
268		if (foundDescribe && foundName && foundLeft) {
269			working ~= currentToken;
270		}
271	}
272}
273
274class ParseDescribeSection : ParseUnit
275{
276	this() {
277		working = "";
278
279		registerToken("describe", &parseDescribe);
280		registerToken("it", &parseIt);
281		registerToken("done", &parseDone);
282
283		registerToken("{", &parseLeft);
284		registerToken("}", &parseRight);
285	}
286
287protected:
288
289	bool foundDescribe = false;
290	bool foundName = false;
291	int foundLeft = 0;
292
293	string name;
294
295	string working;
296
297	void parseDescribe() {
298		if (foundDescribe) {
299			// error
300		}
301		else {
302			foundDescribe = true;
303		}
304	}
305
306	void parseIt() {
307		if (working.length > 0) {
308			AST ast = new AST(null, null);
309			ast.value = working;
310			progressTree(ast);
311
312			working = "";
313		}
314
315		AST section;
316		section = newParseUnit(new ParseIt());
317
318		progressTree(section);
319	}
320
321	void parseLeft() {
322		foundLeft++;
323		if (foundLeft > 1) {
324			working ~= currentToken;
325		}
326	}
327
328	void parseRight() {
329		foundLeft--;
330		if (foundLeft == 0) {
331			// done
332			if (working.length > 0) {
333				AST ast = new AST(null, null);
334				ast.value = working;
335				progressTree(ast);
336
337				working = "";
338			}
339			done();
340		}
341		else {
342			working ~= currentToken;
343		}
344	}
345
346	void parseDone() {
347		if (working.length > 0) {
348			AST ast = new AST(null, null);
349			ast.value = working;
350			progressTree(ast);
351
352			working = "";
353		}
354
355		AST section;
356		section = newParseUnit(new ParseDone());
357
358		progressTree(section);
359	}
360
361	void parseDefault() {
362		if (foundDescribe && !foundName && !foundLeft && !isDelimiter(currentToken)) {
363			foundName = true;
364			name = currentToken;
365			//Console.putln("Class: ", name.array);
366
367			AST meta = new AST(null, new AST(null, null));
368			meta.name = "Identifier";
369			meta.right.value = name;
370			progressTree(meta);
371		}
372		if (foundDescribe && foundName && foundLeft) {
373			working ~= currentToken;
374		}
375	}
376
377	// Parses:
378
379	// describe section {
380	//
381	//     it should {
382	//     }
383	//
384	// }
385
386	// Passes off control:
387
388	// ParseIt()
389	// ParseDescribe()
390
391}
392
393class ParseIt : ParseUnit {
394	this() {
395		working = "";
396
397		registerToken("{", &parseLeft);
398		registerToken("}", &parseRight);
399
400		registerToken("it", &parseIt);
401
402		registerToken("should", &parseShould);
403		registerToken("shouldNot", &parseShould);
404		registerToken("shouldThrow", &parseShould);
405	}
406
407	bool foundIt = false;
408	bool foundName = false;
409	int foundLeft = 0;
410
411	string name;
412
413	string working;
414
415	void parseShould() {
416		if(!foundIt) {
417			// error
418		}
419		else {
420			if (working.length > 0) {
421				AST ast = new AST(null, null);
422				ast.value = working;
423				progressTree(ast);
424
425				working = "";
426			}
427
428			AST section;
429			if (currentToken == "should") {
430				section = newParseUnit(new ParseShould());
431			}
432			else if (currentToken == "shouldThrow") {
433				section = newParseUnit(new ParseShouldThrow());
434			}
435			else {
436				section = newParseUnit(new ParseShouldNot());
437			}
438
439			progressTree(section);
440		}
441	}
442
443	void parseIt() {
444		if (!foundIt) {
445			foundIt = true;
446		}
447	}
448
449	void parseLeft() {
450		foundLeft++;
451		if (foundLeft > 1) {
452			working ~= currentToken;
453		}
454	}
455
456	void parseRight() {
457		foundLeft--;
458		if (foundLeft == 0) {
459			// done
460			if (working.length > 0) {
461				AST ast = new AST(null, null);
462				ast.value = working;
463				progressTree(ast);
464
465				working = "";
466			}
467			done();
468		}
469		else {
470			working ~= currentToken;
471		}
472	}
473
474	void parseDefault() {
475		if (foundIt && !foundName && !foundLeft && !isDelimiter(currentToken)) {
476			foundName = true;
477			name = currentToken;
478			//Console.putln("It: ", name.array, " @ ", feeder.getLineNumber());
479
480			AST meta = new AST(null, new AST(null, null));
481			meta.name = "Identifier";
482			meta.right.value = name;
483			progressTree(meta);
484
485			ulong lnum = feeder.getLineNumber();
486			meta = new AST(null, new AST(null, null));
487			meta.name = "LineNumber";
488			meta.right.value = lnum;
489			progressTree(meta);
490		}
491		if (foundIt && foundName && foundLeft) {
492			working ~= currentToken;
493		}
494	}
495}
496
497class ParseShould : ParseUnit {
498	this() {
499		working = "";
500
501		registerToken("(", &parseLeft);
502		registerToken(")", &parseRight);
503	}
504
505	bool foundShould;
506
507	uint parens = 0;
508
509	string working;
510
511	void parseLeft() {
512		if (parens != 0) {
513			working ~= currentToken;
514		}
515		parens++;
516	}
517
518	void parseRight() {
519		parens--;
520		if (parens == 0) {
521			// done
522			if (working.length > 0) {
523				AST ast = new AST(null, null);
524				ast.value = working;
525				progressTree(ast);
526
527				working = "";
528			}
529			done();
530		}
531		else {
532			working ~= currentToken;
533		}
534	}
535
536	void parseDefault() {
537		if (currentToken == "should" && !foundShould) {
538			foundShould = true;
539		}
540		else if (currentToken == "shouldNot" && !foundShould) {
541			foundShould = true;
542		}
543		else if (currentToken == "shouldThrow" && !foundShould) {
544			foundShould = true;
545		}
546		else {
547			working ~= currentToken;
548		}
549	}
550}
551
552class ParseShouldNot : ParseShould {
553}
554
555class ParseShouldThrow : ParseShould {
556}
557
558class ParseDone : ParseUnit
559{
560	this()
561	{		
562		registerToken("done", &parseDone);
563		registerToken("before", &parseBefore);
564		
565		registerToken("{", &parseLeft);
566		registerToken("}", &parseRight);
567	}
568	
569	int foundLeft = 0;
570	bool foundDone = false;
571	bool foundBefore = false;
572	
573	string working;
574	
575	void parseDone() {
576		if (foundDone) {
577			// error
578		}
579		else {
580			foundDone = true;
581		}
582	}
583
584	void parseLeft() {
585		foundLeft++;
586		if (foundLeft > 1) {
587			working ~= currentToken;
588		}
589	}
590
591	void parseRight() {
592		foundLeft--;
593		if (foundLeft == 0) {
594			// done
595			if (working.length > 0) {
596				AST ast = new AST(null, null);
597				ast.value = working;
598				progressTree(ast);
599
600				working = "";
601			}
602			done();
603		}
604		else {
605			working ~= currentToken;
606		}
607	}
608
609	void parseBefore() {
610		if (foundDone && !foundBefore && !foundLeft) {
611			foundBefore = true;
612		}
613		else {
614			 // error
615		}
616	}
617
618	void parseDefault() {
619		if (foundDone && foundBefore && foundLeft) {
620			working ~= currentToken;
621		}
622	}
623}