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