PageRenderTime 54ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Compiler.cs

https://bitbucket.org/cvillamor/compiler
C# | 1616 lines | 1062 code | 318 blank | 236 comment | 424 complexity | b064b864656753df0051ab6bdab7d4a1 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. namespace Compiler_
  7. {
  8. class Compiler
  9. {
  10. public Scanner scan;
  11. private Grammar grammar;
  12. private Token CURRENT_TOKEN;
  13. private Stack<Dictionary<string, Record>> SYMBOL_TABLE_STACK;
  14. private Dictionary<string, GotoRecord> GOTO_RECORDS;
  15. private int ADDRESS = 0;
  16. private RunTimeModule runtimemod;
  17. //TK_GOTO
  18. private int OLD_LEVEL;
  19. private string CURRENT_STRING;
  20. private int CURRENT_LEVEL;
  21. private bool incremented = false;
  22. public Compiler(string FILE)
  23. {
  24. StreamReader reader = new StreamReader(FILE);
  25. char[] INPUT = reader.ReadToEnd().ToLower().ToCharArray();
  26. SYMBOL_TABLE_STACK = new Stack<Dictionary<string, Record>>();
  27. scan = new Scanner(FILE, INPUT, SYMBOL_TABLE_STACK);
  28. runtimemod = new RunTimeModule();
  29. GOTO_RECORDS = new Dictionary<string, GotoRecord>();
  30. //grammar = new Grammar();
  31. //Add the System calls table
  32. SystemC sys = new SystemC();
  33. SYMBOL_TABLE_STACK.Push(sys.SystemCalls);
  34. //For GOTO
  35. OLD_LEVEL = 0;
  36. CURRENT_LEVEL = 0;
  37. CURRENT_STRING = "";
  38. }
  39. public void Run()
  40. {
  41. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  42. try {
  43. do
  44. {
  45. switch (CURRENT_TOKEN.TOKEN_TYPE)
  46. {
  47. //Handle the Program grammar
  48. case(TOKEN_TYPES.TK_PROGRAM) :
  49. ProgramGrammar();
  50. break;
  51. //Handle the Variable grammar
  52. case(TOKEN_TYPES.TK_VAR) :
  53. VarDeclGrammar();
  54. break;
  55. //Handle the Label grammar
  56. case(TOKEN_TYPES.TK_LABEL) :
  57. LabelDeclGrammar();
  58. break;
  59. //Handle the Procedure grammar
  60. case(TOKEN_TYPES.TK_PROCEDURE) :
  61. ProcedureDeclGrammar();
  62. break;
  63. //Hande the Begin Grammar
  64. case(TOKEN_TYPES.TK_BEGIN) :
  65. BeginGrammar();
  66. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  67. break;
  68. }
  69. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON || CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_END)
  70. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  71. } while (scan.TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_EOF && scan.TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ERROR && scan.TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_DOTOP);
  72. }
  73. catch(SyntaxErrorException ex)
  74. {
  75. Console.WriteLine(ex.Message);
  76. }
  77. //Patch Up Holes from the Gotos
  78. PatchUp();
  79. //END PROGRAM
  80. runtimemod.CodeStackPush(OPCODES.OP_HALT.ToString());
  81. //Reverse Stack
  82. if(runtimemod.Stack.Count!=0)
  83. {
  84. Queue<object> derp = new Queue<object>();
  85. for(int i=runtimemod.Stack.Count; i>0; i--)
  86. derp.Enqueue(runtimemod.Stack.Pop());
  87. for (int i=derp.Count; i>0; i--)
  88. runtimemod.Stack.Push(derp.Dequeue());
  89. }
  90. //RUN CS
  91. runtimemod.Run();
  92. }
  93. public void DeclarationGrammar()
  94. {
  95. do
  96. {
  97. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  98. switch (CURRENT_TOKEN.TOKEN_TYPE)
  99. {
  100. case(TOKEN_TYPES.TK_VAR) :
  101. VarDeclGrammar();
  102. break;
  103. case(TOKEN_TYPES.TK_LABEL) :
  104. LabelDeclGrammar();
  105. break;
  106. }
  107. } while (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_BEGIN);
  108. }
  109. public void ProgramGrammar()
  110. {
  111. do
  112. {
  113. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  114. }
  115. while (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_SEMICOLON);
  116. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  117. }
  118. #region DECLARATION
  119. //----------------------DECLARATION GRAMMAR----------------------------------
  120. //Declarations
  121. public void LabelDeclGrammar()
  122. {
  123. List<string> NAMELIST = new List<string>();
  124. //Variable expression grammar, keep looping until we hit semicolon
  125. while (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_SEMICOLON)
  126. {
  127. //Scan for a TK_ID type
  128. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  129. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ID)
  130. {
  131. throw new SyntaxErrorException("Bad Formatting on Line " + CURRENT_TOKEN.TOKEN_LINE + " column " + CURRENT_TOKEN.TOKEN_COL);
  132. }
  133. else
  134. {
  135. //Add the TK_ID to NameList
  136. NAMELIST.Add(CURRENT_TOKEN.TOKEN_VALUE.ToString());
  137. }
  138. //Scan for a comma or a semi-colon
  139. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  140. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_COMMAOP && CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_SEMICOLON)
  141. {
  142. throw new SyntaxErrorException("Bad Formatting on Line " + CURRENT_TOKEN.TOKEN_LINE + " column " + CURRENT_TOKEN.TOKEN_COL);
  143. }
  144. }
  145. //Check No repeats in nameList
  146. if (!noRepeatedIdentifiers(NAMELIST))
  147. throw new SyntaxErrorException("Invalid repition of identifiers on Line " + CURRENT_TOKEN.TOKEN_LINE);
  148. //Create Symbol Table!
  149. CreateDeclLabelSymbolTable(NAMELIST, TYPE.Label);
  150. }
  151. public void ProcedureDeclGrammar()
  152. {
  153. //Get Name
  154. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  155. //Save the base of the Symbol Table Stack
  156. int count = SYMBOL_TABLE_STACK.Count;
  157. //Create Symbol table for this procedure
  158. CreateDeclProcSymbolTable((string)CURRENT_TOKEN.TOKEN_VALUE);
  159. //Declaration Grammar
  160. DeclarationGrammar();
  161. BeginGrammar();
  162. //Patch up the holes up to a certain call
  163. PatchUp(SYMBOL_TABLE_STACK.Count - count);
  164. //Get rid of the symbol Table
  165. RenderDataSegment(count);
  166. runtimemod.CodeStackPush(OPCODES.OP_RETURN.ToString());
  167. runtimemod.StartIP = runtimemod.IP;
  168. }
  169. //Pop Symbol table till we get rid of all procedure information
  170. public void RenderDataSegment(int count)
  171. {
  172. for (int i = SYMBOL_TABLE_STACK.Count - 1; i > count; i--)
  173. {
  174. SYMBOL_TABLE_STACK.Pop();
  175. }
  176. }
  177. public void VarDeclGrammar()
  178. {
  179. List<NameList> varList = new List<NameList>();
  180. List<string> NAMELIST = new List<string>();
  181. //Variable expression grammar, keep looping until we hit TK begin
  182. while (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_BEGIN && CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_PROCEDURE)
  183. {
  184. //Scan for a TK_ID type
  185. if(CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ID)
  186. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  187. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  188. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  189. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ID)
  190. {
  191. throw new SyntaxErrorException("Bad Formatting on Line " + CURRENT_TOKEN.TOKEN_LINE + " column " + CURRENT_TOKEN.TOKEN_COL);
  192. }
  193. else
  194. {
  195. //Add the TK_ID to NameList
  196. NAMELIST.Add(CURRENT_TOKEN.TOKEN_VALUE.ToString());
  197. }
  198. //Scan for a comma
  199. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  200. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_COMMAOP && CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_COLONOP)
  201. {
  202. throw new SyntaxErrorException("Bad Formatting on Line " + CURRENT_TOKEN.TOKEN_LINE + " column " + CURRENT_TOKEN.TOKEN_COL);
  203. }
  204. //Scan for terminator(TK_COLONOP)
  205. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_COLONOP)
  206. {
  207. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  208. //Check if array
  209. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_ARRAY)
  210. {
  211. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  212. //Match [
  213. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_LARRAYBRACK)
  214. throw new TokenTypeMismatchException("Expected [ ");
  215. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  216. //Match if a character or a int literal
  217. if(CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_INTLIT &&
  218. CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ID )
  219. throw new TokenTypeMismatchException("Expected [ ");
  220. int lo;
  221. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_INTLIT)
  222. {
  223. lo = Convert.ToInt32(CURRENT_TOKEN.TOKEN_VALUE);
  224. if (lo < 0)
  225. throw new ArrayTypeMismatchException("Range must be greater than 0");
  226. }
  227. else
  228. {
  229. lo = (char)CURRENT_TOKEN.TOKEN_VALUE;
  230. }
  231. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  232. //Match ..
  233. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ARRAYRNGOP)
  234. throw new TokenTypeMismatchException("Expected .. ");
  235. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  236. //Match if a character or a int literal
  237. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_INTLIT &&
  238. CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ID)
  239. throw new TokenTypeMismatchException("Expected [ ");
  240. int hi;
  241. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_INTLIT)
  242. {
  243. hi = Convert.ToInt32(CURRENT_TOKEN.TOKEN_VALUE);
  244. if (lo < 0)
  245. throw new ArrayTypeMismatchException("Range must be greater than 0");
  246. }
  247. else
  248. {
  249. hi = (char)CURRENT_TOKEN.TOKEN_VALUE;
  250. }
  251. // ]
  252. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  253. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RARRAYBRACK)
  254. throw new TokenTypeMismatchException("Expected ]");
  255. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  256. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_OF)
  257. throw new TokenTypeMismatchException("Expected TK_OF");
  258. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  259. TYPE t = GetType(CURRENT_TOKEN);
  260. foreach (string name in NAMELIST)
  261. varList.Add(new NameList(name, t, lo, hi, hi-lo+1,true ));
  262. NAMELIST.Clear();
  263. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  264. if(CURRENT_TOKEN.TOKEN_TYPE==TOKEN_TYPES.TK_SEMICOLON)
  265. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  266. }
  267. else
  268. {
  269. //NEED TO CHECK FOR BOOLEAN OR CHAR OR STRING OR REAL
  270. TYPE T = GetType(CURRENT_TOKEN);
  271. foreach (string name in NAMELIST)
  272. varList.Add(new NameList(name, T));
  273. NAMELIST.Clear();
  274. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  275. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  276. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  277. }
  278. }
  279. }
  280. //Check No repeats in nameList
  281. if (!noRepeatedIdentifiers(varList))
  282. throw new SyntaxErrorException("Invalid repition of identifiers on Line " + CURRENT_TOKEN.TOKEN_LINE);
  283. //Pass the right token Type)
  284. //Create Symbol Table!
  285. CreateDeclVarSymbolTable(varList);
  286. }
  287. //----------------------DECLARATION GRAMMAR----------------------------------
  288. #endregion
  289. public void BeginGrammar()
  290. {
  291. //CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  292. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  293. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  294. StatementGrammar(true);
  295. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON || CURRENT_TOKEN.TOKEN_TYPE==TOKEN_TYPES.TK_END)
  296. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  297. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  298. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  299. }
  300. #region STATEMENT
  301. //----------------------STATEMENT GRAMMAR----------------------------------
  302. /** <Statement> -->
  303. * <If>;<STATEMENT>
  304. * <Repeat>;<STATEMENT>
  305. * <Assignment>;<STATEMENT>
  306. * <While>;<STATEMENT>
  307. */
  308. public void StatementGrammar(bool begin=false)
  309. {
  310. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  311. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  312. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  313. bool statement = true;
  314. while (statement)
  315. {
  316. switch (CURRENT_TOKEN.TOKEN_TYPE)
  317. {
  318. case (TOKEN_TYPES.TK_BEGIN):
  319. OpenLevel();
  320. BeginGrammar();
  321. CloseLevel();
  322. break;
  323. case (TOKEN_TYPES.TK_IF):
  324. OpenLevel();
  325. IfGrammar();
  326. CloseLevel();
  327. break;
  328. case (TOKEN_TYPES.TK_VAR):
  329. case (TOKEN_TYPES.TK_ID):
  330. AssignmentGrammar();
  331. break;
  332. case (TOKEN_TYPES.TK_REPEAT):
  333. OpenLevel();
  334. RepeatGrammar();
  335. CloseLevel();
  336. break;
  337. case (TOKEN_TYPES.TK_WHILE) :
  338. OpenLevel();
  339. WhileGrammar();
  340. CloseLevel();
  341. break;
  342. case (TOKEN_TYPES.TK_FOR) :
  343. OpenLevel();
  344. ForGrammar();
  345. CloseLevel();
  346. break;
  347. case (TOKEN_TYPES.TK_LABEL) :
  348. LabelGrammar();
  349. break;
  350. case (TOKEN_TYPES.TK_GOTO) :
  351. GotoGrammar();
  352. break;
  353. case (TOKEN_TYPES.TK_SYS_PROC):
  354. case (TOKEN_TYPES.TK_SYS_FUNC):
  355. SysCallGrammar();
  356. break;
  357. case (TOKEN_TYPES.TK_PROCEDURE):
  358. ProcCallGrammar();
  359. break;
  360. default:
  361. statement = false;
  362. break;
  363. }
  364. if (!begin)
  365. return;
  366. }
  367. }
  368. /**
  369. * TK_PROCEDURE -->
  370. *
  371. *
  372. */
  373. public void ProcCallGrammar()
  374. {
  375. Token tk = new Token(CURRENT_TOKEN);
  376. int address = -1;
  377. TYPE type = TYPE.E;
  378. Lookup(tk, ref address, ref type);
  379. if (address != -1)
  380. {
  381. runtimemod.CodeStackPush(address.ToString());
  382. runtimemod.CodeStackPush(OPCODES.OP_JMP.ToString());
  383. runtimemod.StackPush(runtimemod.IP);
  384. }
  385. else
  386. throw new TokenTypeMismatchException("Procedure not found");
  387. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  388. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_LPARENOP)
  389. throw new TokenTypeMismatchException("Expecting left paren");
  390. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  391. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RPARENOP)
  392. throw new TokenTypeMismatchException("Expecting right paren");
  393. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  394. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  395. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  396. }
  397. /**
  398. * <Procedure> -->
  399. * TK_SYS_PROC | TK_SYS_FUNC
  400. *
  401. */
  402. public void SysCallGrammar()
  403. {
  404. Token tk = new Token(CURRENT_TOKEN);
  405. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  406. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_LPARENOP)
  407. throw new TokenTypeMismatchException("Expecting open paren");
  408. TYPE t = Expression();
  409. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RPARENOP)
  410. throw new TokenTypeMismatchException("Expecting close paren");
  411. switch (tk.VALUE)
  412. {
  413. case ("abs") :
  414. if (t != TYPE.Real && t != TYPE.Integer)
  415. throw new TokenTypeMismatchException("Expecting a Real or Integer type inside abs function");
  416. runtimemod.CodeStackPush(OPCODES.OP_ABS.ToString());
  417. break;
  418. case ("write") :
  419. if (t != TYPE.String && t != TYPE.Integer && t != TYPE.Character && t != TYPE.Boolean)
  420. throw new TokenTypeMismatchException("Not a valid function to use to write");
  421. runtimemod.CodeStackPush(OPCODES.OP_WRITE.ToString());
  422. break;
  423. case ("writeln") :
  424. if (t != TYPE.String && t != TYPE.Integer && t != TYPE.Character && t != TYPE.Boolean)
  425. throw new TokenTypeMismatchException("Not a valid function to use to write");
  426. runtimemod.CodeStackPush(OPCODES.OP_WRITELN.ToString());
  427. break;
  428. }
  429. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  430. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  431. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  432. }
  433. /**
  434. * <For> -->
  435. * for <VAR> := <EXPRESSION> [to|downto] do <STATEMENT>
  436. *
  437. */
  438. public void ForGrammar()
  439. {
  440. //Get a value
  441. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  442. //address of token
  443. int TOKEN_ADR=-1;
  444. TYPE TOKEN_TYPE = TYPE.E;
  445. //Check the symbol table for the CURRENT_TOKEN
  446. Lookup(CURRENT_TOKEN, ref TOKEN_ADR, ref TOKEN_TYPE);
  447. //Check if value was declared AND it's of type integer
  448. if ((CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_VAR && CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_ID)
  449. || TOKEN_TYPE != TYPE.Integer)
  450. throw new TokenTypeMismatchException("Not a valid var identifier");
  451. // :=
  452. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  453. if (CURRENT_TOKEN.TOKEN_TYPE!=TOKEN_TYPES.TK_COLEQOP)
  454. throw new TokenTypeMismatchException("Expecting COLEQOP identifier");
  455. //Push the value into the Code stack
  456. Expression();
  457. //Push address of LHS
  458. runtimemod.CodeStackPush("@" + TOKEN_ADR.ToString());
  459. //Set Equal
  460. runtimemod.CodeStackPush(OPCODES.OP_ASSIGN.ToString());
  461. //target
  462. int target = runtimemod.IP;
  463. //Advance CURRENT TOKEN to check for TK_TO or TK_DOWNTO
  464. if(CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_TO && CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_DOWNTO)
  465. throw new TokenTypeMismatchException("Expected either TK_TO or TK_DOWNTO");
  466. TOKEN_TYPES TypeOfFor = CURRENT_TOKEN.TOKEN_TYPE;
  467. //Push address of LHS
  468. runtimemod.CodeStackPush("@" + TOKEN_ADR.ToString());
  469. //Get stop for the loop
  470. Expression();
  471. //Check the Equal
  472. if (TypeOfFor == TOKEN_TYPES.TK_TO)
  473. runtimemod.CodeStackPush(OPCODES.OP_GT.ToString());
  474. else
  475. runtimemod.CodeStackPush(OPCODES.OP_LT.ToString());
  476. //Generate hole
  477. int hole = runtimemod.IP;
  478. //hole location
  479. runtimemod.CodeStackPush("0");
  480. //Jump out if true
  481. runtimemod.CodeStackPush(OPCODES.OP_JTRUE.ToString());
  482. if(CURRENT_TOKEN.TOKEN_TYPE!=TOKEN_TYPES.TK_DO)
  483. throw new TokenTypeMismatchException("Expected TK_DO");
  484. StatementGrammar();
  485. runtimemod.CodeStackPush("@" + TOKEN_ADR.ToString());
  486. runtimemod.CodeStackPush("1");
  487. //Add 1
  488. if (TypeOfFor == TOKEN_TYPES.TK_TO)
  489. runtimemod.CodeStackPush(OPCODES.OP_ADD.ToString());
  490. else
  491. runtimemod.CodeStackPush(OPCODES.OP_SUBTRACT.ToString());
  492. runtimemod.CodeStackPush("@" + TOKEN_ADR.ToString());
  493. runtimemod.CodeStackPush(OPCODES.OP_ASSIGN.ToString());
  494. //Jump to target
  495. runtimemod.CodeStackPush(target.ToString());
  496. //JMP
  497. runtimemod.CodeStackPush(OPCODES.OP_JMP.ToString());
  498. int save_ip = runtimemod.IP;
  499. runtimemod.IP = hole;
  500. runtimemod.CodeStackPush(save_ip.ToString());
  501. runtimemod.IP = save_ip;
  502. }
  503. /**
  504. * <Label> -->
  505. * TK_LABEL <Statement>
  506. *
  507. */
  508. public void LabelGrammar()
  509. {
  510. //Get the record for this grammar
  511. LabelRecord rec = (LabelRecord)Lookup(CURRENT_TOKEN);
  512. if (rec == null)
  513. throw new TokenTypeMismatchException("This label does not exist");
  514. if (rec.seen)
  515. throw new TokenTypeMismatchException("This label exists more than once!");
  516. else
  517. {
  518. rec.seen = true;
  519. rec.address = runtimemod.IP;
  520. rec.scope = CURRENT_STRING;
  521. }
  522. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  523. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_COLONOP)
  524. throw new TokenTypeMismatchException("Expected a colon");
  525. StatementGrammar();
  526. }
  527. /**
  528. * PatchUp
  529. *
  530. */
  531. public void PatchUp()
  532. {
  533. Stack<Dictionary<string, Record>> tempStack = new Stack<Dictionary<string, Record>>();
  534. int STACK_COUNT = SYMBOL_TABLE_STACK.Count;
  535. //return if the SYMBOL TABLE IS EMPTY
  536. if (SYMBOL_TABLE_STACK.Count == 0)
  537. return;
  538. while (SYMBOL_TABLE_STACK.Count != 0)
  539. {
  540. Dictionary<string, Record> symbolTable = SYMBOL_TABLE_STACK.Pop();
  541. tempStack.Push(symbolTable);
  542. foreach (KeyValuePair<string, Record> keyV in symbolTable)
  543. if (keyV.Value.TYPE_LT == TOKEN_TYPES.TK_LABEL)
  544. {
  545. LabelRecord rec = (LabelRecord)keyV.Value;
  546. if (!rec.seen && rec.GOTO_RECORDS.Count != 0)
  547. throw new TokenTypeMismatchException("Error: something with labels");
  548. else if(rec.seen)
  549. {
  550. //Fill up the hole
  551. int save_ip = runtimemod.IP;
  552. runtimemod.IP = rec.GOTO_RECORDS[rec.value.ToString()].hole;
  553. runtimemod.CodeStackPush(rec.address.ToString());
  554. runtimemod.IP = save_ip;
  555. if (!rec.GOTO_RECORDS[rec.value.ToString()].scope.Contains(rec.scope))
  556. throw new Exception("Error jumping to that scope friend!");
  557. }
  558. }
  559. }
  560. //Pop SymbolTables back into the SYMBOL_TABLE_STACK
  561. for (int i = 0; i < STACK_COUNT; i++)
  562. SYMBOL_TABLE_STACK.Push(tempStack.Pop());
  563. }
  564. /**
  565. * PatchUp
  566. *
  567. */
  568. public void PatchUp(int limit)
  569. {
  570. Stack<Dictionary<string, Record>> tempStack = new Stack<Dictionary<string, Record>>();
  571. int STACK_COUNT = SYMBOL_TABLE_STACK.Count;
  572. //return if the SYMBOL TABLE IS EMPTY
  573. if (SYMBOL_TABLE_STACK.Count == 0)
  574. return;
  575. for(int i=0; i<limit; i++)
  576. {
  577. Dictionary<string, Record> symbolTable = SYMBOL_TABLE_STACK.Pop();
  578. tempStack.Push(symbolTable);
  579. foreach (KeyValuePair<string, Record> keyV in symbolTable)
  580. if (keyV.Value.TYPE_LT == TOKEN_TYPES.TK_LABEL)
  581. {
  582. LabelRecord rec = (LabelRecord)keyV.Value;
  583. if (!rec.seen && rec.GOTO_RECORDS.Count != 0)
  584. throw new TokenTypeMismatchException("Error: something with labels");
  585. else if (rec.seen)
  586. {
  587. //Fill up the hole
  588. int save_ip = runtimemod.IP;
  589. runtimemod.IP = rec.GOTO_RECORDS[rec.value.ToString()].hole;
  590. runtimemod.CodeStackPush(rec.address.ToString());
  591. runtimemod.IP = save_ip;
  592. }
  593. }
  594. }
  595. //Pop SymbolTables back into the SYMBOL_TABLE_STACK
  596. for (int i = 0; i < limit; i++)
  597. SYMBOL_TABLE_STACK.Push(tempStack.Pop());
  598. }
  599. /**
  600. * <Goto> -->
  601. * TK_GOTO TK_LABEL
  602. *
  603. */
  604. public void GotoGrammar()
  605. {
  606. //TK_GOTO SHOULD ALREADY BE MATCHED
  607. //Match TK_LABEL
  608. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  609. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_LABEL)
  610. throw new TokenTypeMismatchException("Error Expected a label to be referenced after GOTO");
  611. //Generate hole
  612. int hole = runtimemod.IP;
  613. //hole location
  614. runtimemod.CodeStackPush("0");
  615. //Jump out if true
  616. runtimemod.CodeStackPush(OPCODES.OP_JMP.ToString());
  617. //TODO: Append to GOTO_RECORDS
  618. GotoRecord record = new GotoRecord();
  619. record.hole = hole;
  620. record.scope = CURRENT_STRING;
  621. //TODO: SET THIS record.scope
  622. //TODO: SET THIS record.secRef
  623. GOTO_RECORDS.Add(CURRENT_TOKEN.TOKEN_VALUE.ToString(), record);
  624. //Match TK_LABEL
  625. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  626. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  627. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  628. }
  629. /**
  630. * <If> -->
  631. * <COND> THEN <STAT>
  632. * <COND> THEN <STAT> ELSE <STAT>
  633. */
  634. public void IfGrammar()
  635. {
  636. int save_ip;
  637. //Get the Expression
  638. Condition();
  639. //Set the hole to IP
  640. int hole = runtimemod.IP;
  641. //Generate Address -- Generate hole
  642. runtimemod.CodeStackPush("0");
  643. //Generate the JFALSE
  644. runtimemod.CodeStackPush(OPCODES.OP_JFALSE.ToString());
  645. //Forward CURRENT_TOKEN to check the TK_THEN
  646. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_THEN)
  647. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  648. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_THEN)
  649. throw new TokenTypeMismatchException("Expecting THEN statement not found");
  650. //Statement grammars
  651. StatementGrammar();
  652. //Advance if we find a semicolon
  653. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  654. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  655. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_ELSE)
  656. {
  657. //Create hole 2
  658. int hole2 = runtimemod.IP;
  659. //Generate Address -- Second hole
  660. runtimemod.CodeStackPush("0");
  661. //OPCODE
  662. runtimemod.CodeStackPush(OPCODES.OP_JMP.ToString());
  663. //Save_IP
  664. save_ip = runtimemod.IP;
  665. runtimemod.IP = hole;
  666. //Generate address
  667. runtimemod.CodeStackPush(save_ip.ToString());
  668. runtimemod.IP = save_ip;
  669. hole = hole2;
  670. StatementGrammar();
  671. }
  672. save_ip = runtimemod.IP;
  673. runtimemod.IP = hole;
  674. runtimemod.CodeStackPush(save_ip.ToString());
  675. runtimemod.IP = save_ip;
  676. }
  677. /**
  678. * <Assignment> -->
  679. * <LHS> = <RHS>
  680. * <LHS> = TK_A_VAR
  681. * <RHS> = <Expression>
  682. */
  683. public void AssignmentGrammar()
  684. {
  685. //Check if current TK_VAR or TK_ID is in symbol table
  686. if (!VarExists(CURRENT_TOKEN.VALUE))
  687. throw new TokenTypeMismatchException("Value doesn't exist");
  688. //Array
  689. int address = -1;
  690. TYPE type = TYPE.E;
  691. //Lookup the array type.
  692. Lookup(CURRENT_TOKEN, ref address, ref type);
  693. if (type == TYPE.Array)
  694. {
  695. //Store the array identifier
  696. Token arrayT = new Token(CURRENT_TOKEN);
  697. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  698. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_LARRAYBRACK)
  699. throw new TokenTypeMismatchException("Left Bracket expected");
  700. TYPE t = Expression();
  701. if (t != TYPE.Integer)
  702. throw new TokenTypeMismatchException("Expected Array Index of Integer type");
  703. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RARRAYBRACK)
  704. throw new TokenTypeMismatchException("Right Bracket expected");
  705. ArrayRecord rec = (ArrayRecord)Lookup(arrayT);
  706. if (rec.lo != 0)
  707. runtimemod.CodeStackPush(rec.lo.ToString());
  708. runtimemod.CodeStackPush(OPCODES.OP_SUBTRACT.ToString());
  709. runtimemod.CodeStackPush(rec.address.ToString());
  710. runtimemod.CodeStackPush(OPCODES.OP_ADD.ToString());
  711. //Get the Type of Token Operator should only support COLEQOP for now
  712. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  713. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_COLEQOP)
  714. {
  715. TYPE RHS = Expression();
  716. //Make sure expression is terminated by comma
  717. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  718. {
  719. if (TypeCheck(rec.TYPE, RHS, TOKEN_TYPES.TK_COLEQOP))
  720. {
  721. //Push the value we get for the LHS
  722. runtimemod.CodeStackPush(OPCODES.OP_ARRAYASSIGN.ToString());
  723. }
  724. }
  725. }
  726. else
  727. throw new TokenTypeMismatchException("Command not recognized");
  728. }
  729. else
  730. {
  731. //Store Left Hand Side
  732. Token LHS = new Token(CURRENT_TOKEN);
  733. //Get the record for this Token.
  734. Record LHSRec = Lookup(LHS);
  735. //Get the Type of Token Operator should only support COLEQOP for now
  736. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  737. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_COLEQOP)
  738. {
  739. TYPE RHS = Expression();
  740. //Make sure expression is terminated by comma
  741. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  742. {
  743. if (TypeCheck(LHSRec.TYPE, RHS, TOKEN_TYPES.TK_COLEQOP))
  744. {
  745. //Push the value we get for the LHS
  746. runtimemod.CodeStackPush("@" + LHSRec.address);
  747. runtimemod.CodeStackPush(OPCODES.OP_ASSIGN.ToString());
  748. }
  749. }
  750. }
  751. else
  752. throw new TokenTypeMismatchException("Command not recognized");
  753. }
  754. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  755. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  756. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  757. }
  758. /** <Repeat> -->
  759. * Repeat <STATEMENT> Until <CONDITION>
  760. *
  761. */
  762. public void RepeatGrammar()
  763. {
  764. //Temporarily targit the runtime instruction pointer
  765. int target = runtimemod.IP;
  766. //Call statement grammar to parse next statement on line
  767. StatementGrammar();
  768. //Match TK_UNTIL
  769. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_UNTIL)
  770. throw new TokenTypeMismatchException("until keyword missing. exiting program");
  771. //Ensure there's a condition expression after TK_UNTIL
  772. Condition();
  773. //GEN_ADDRESS
  774. runtimemod.CodeStackPush(target.ToString());
  775. //GEN_OPCODE
  776. runtimemod.CodeStackPush(OPCODES.OP_JFALSE.ToString());
  777. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  778. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_SEMICOLON)
  779. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  780. }
  781. public void WhileGrammar()
  782. {
  783. //get the target
  784. int target = runtimemod.IP;
  785. //Condition
  786. Condition();
  787. int hole = runtimemod.IP;
  788. //Generate Address
  789. runtimemod.CodeStackPush("0");
  790. //Generate OPCODE
  791. runtimemod.CodeStackPush(OPCODES.OP_JFALSE.ToString());
  792. //run statements
  793. StatementGrammar();
  794. //Generate Address
  795. runtimemod.CodeStackPush(target.ToString());
  796. //Generate Opcode
  797. runtimemod.CodeStackPush(OPCODES.OP_JMP.ToString());
  798. //switch target
  799. target = runtimemod.IP;
  800. //Patch up hole
  801. runtimemod.IP = hole;
  802. //Gen address
  803. runtimemod.CodeStackPush(target.ToString());
  804. //Reset target
  805. runtimemod.IP = target;
  806. }
  807. //Checks the conditional is valid in a repeat grammar
  808. //Do we add this to everything else?
  809. public void Condition()
  810. {
  811. TYPE t = Expression();
  812. if (t != TYPE.Boolean)
  813. throw new TokenTypeMismatchException("Not a boolean expression. exiting program");
  814. }
  815. //----------------------STATEMENT GRAMMAR----------------------------------
  816. #endregion
  817. #region Expression
  818. //----------------------EXPRESSION GRAMMAR----------------------------------
  819. public TYPE Expression()
  820. {
  821. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  822. TYPE t1 = TermExpression();
  823. TYPE t2;
  824. while(CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_PLUSOP || CURRENT_TOKEN.TOKEN_TYPE== TOKEN_TYPES.TK_MINUSOP ||
  825. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_OR)
  826. {
  827. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_PLUSOP)
  828. {
  829. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  830. t2 = TermExpression();
  831. if(TypeCheck(t1, t2, TOKEN_TYPES.TK_PLUSOP))
  832. runtimemod.CodeStackPush(OPCODES.OP_ADD.ToString());
  833. }
  834. else if (CURRENT_TOKEN.VALUE == "-")
  835. {
  836. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  837. t2 = TermExpression();
  838. if (TypeCheck(t1, t2, TOKEN_TYPES.TK_MINUSOP))
  839. runtimemod.CodeStackPush(OPCODES.OP_SUBTRACT.ToString());
  840. }
  841. else if (CURRENT_TOKEN.VALUE == "or")
  842. {
  843. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  844. t2 = TermExpression();
  845. if (TypeCheck(t1, t2, TOKEN_TYPES.TK_OR))
  846. runtimemod.CodeStackPush(OPCODES.OP_OR.ToString());
  847. }
  848. }
  849. //Relational Operator
  850. if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_NOTEQOP ||
  851. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_NOTEQ2OP ||
  852. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_LTEQOP ||
  853. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_GTEQOP ||
  854. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_EQUALOP ||
  855. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_LTOP ||
  856. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_GTOP)
  857. {
  858. Token tempCurr = new Token(CURRENT_TOKEN);
  859. Expression();
  860. if (tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_NOTEQOP || tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_NOTEQ2OP)
  861. runtimemod.CodeStackPush(OPCODES.OP_NOTEQ.ToString());
  862. if (tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_LTEQOP)
  863. runtimemod.CodeStackPush(OPCODES.OP_LTEQ.ToString());
  864. if (tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_GTEQOP)
  865. runtimemod.CodeStackPush(OPCODES.OP_GTEQ.ToString());
  866. if (tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_GTOP)
  867. runtimemod.CodeStackPush(OPCODES.OP_GT.ToString());
  868. if (tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_LTOP)
  869. runtimemod.CodeStackPush(OPCODES.OP_LT.ToString());
  870. if (tempCurr.TOKEN_TYPE == TOKEN_TYPES.TK_EQUALOP)
  871. runtimemod.CodeStackPush(OPCODES.OP_EQ.ToString());
  872. return TYPE.Boolean;
  873. }
  874. return t1;
  875. }
  876. public TYPE TermExpression()
  877. {
  878. TYPE f1 = Factor();
  879. TYPE f2;
  880. while(CURRENT_TOKEN.VALUE == "*" || CURRENT_TOKEN.VALUE == "/" || CURRENT_TOKEN.VALUE == "div" ||
  881. CURRENT_TOKEN.VALUE == "and" || CURRENT_TOKEN.VALUE == "mod")
  882. {
  883. if (CURRENT_TOKEN.VALUE == "*")
  884. {
  885. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  886. f2 = Factor();
  887. if(TypeCheck(f1, f2, TOKEN_TYPES.TK_MULTOP))
  888. runtimemod.CodeStackPush(OPCODES.OP_MULT.ToString());
  889. }
  890. else if (CURRENT_TOKEN.VALUE == "/")
  891. {
  892. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  893. f2 = Factor();
  894. if(TypeCheck(f1, f2, TOKEN_TYPES.TK_DIVOP))
  895. runtimemod.CodeStackPush(OPCODES.OP_DIV.ToString());
  896. }
  897. else if (CURRENT_TOKEN.VALUE == "div")
  898. {
  899. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  900. f2 = Factor();
  901. if (TypeCheck(f1, f2, TOKEN_TYPES.TK_DIV))
  902. runtimemod.CodeStackPush(OPCODES.OP_DIV.ToString());
  903. }
  904. else if (CURRENT_TOKEN.VALUE == "and")
  905. {
  906. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  907. f2 = Factor();
  908. if (TypeCheck(f1, f2, TOKEN_TYPES.TK_AND))
  909. runtimemod.CodeStackPush(OPCODES.OP_AND.ToString());
  910. }
  911. else if (CURRENT_TOKEN.VALUE == "mod")
  912. {
  913. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  914. f2 = Factor();
  915. if (TypeCheck(f1, f2, TOKEN_TYPES.TK_MOD))
  916. runtimemod.CodeStackPush(OPCODES.OP_MOD.ToString());
  917. }
  918. }
  919. return (f1);
  920. }
  921. public TYPE Factor()
  922. {
  923. TYPE t = TYPE.E;
  924. if(CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_VAR || CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_ID)
  925. {
  926. int address = -1;
  927. TYPE ty = TYPE.E;
  928. bool noErr = Lookup(CURRENT_TOKEN, ref address, ref ty);
  929. if (ty == TYPE.Array)
  930. {
  931. Token arrayT = new Token(CURRENT_TOKEN);
  932. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  933. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_LARRAYBRACK)
  934. throw new TokenTypeMismatchException("Left Bracket expected");
  935. TYPE t2 = Expression();
  936. if (t2 != TYPE.Integer)
  937. throw new TokenTypeMismatchException("Expected Array Index of Integer type");
  938. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RARRAYBRACK)
  939. throw new TokenTypeMismatchException("Right Bracket expected");
  940. ArrayRecord rec = (ArrayRecord)Lookup(arrayT);
  941. if (rec.lo != 0)
  942. runtimemod.CodeStackPush(rec.lo.ToString());
  943. runtimemod.CodeStackPush(OPCODES.OP_SUBTRACT.ToString());
  944. runtimemod.CodeStackPush(rec.address.ToString());
  945. runtimemod.CodeStackPush(OPCODES.OP_ADD.ToString());
  946. runtimemod.CodeStackPush(OPCODES.OP_GET.ToString());
  947. ty = rec.eltype;
  948. }
  949. else if (noErr) runtimemod.CodeStackPush("@" + address.ToString());
  950. else throw new Exception("Bad variable declaration");
  951. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  952. t = ty;
  953. }
  954. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_INTLIT)
  955. {
  956. runtimemod.CodeStackPush(CURRENT_TOKEN.VALUE);
  957. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  958. t = TYPE.Integer;
  959. }
  960. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_REALLIT)
  961. {
  962. runtimemod.CodeStackPush(CURRENT_TOKEN.VALUE);
  963. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  964. t = TYPE.Real;
  965. }
  966. //Boolean types
  967. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_TRUE ||
  968. CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_FALSE)
  969. {
  970. runtimemod.CodeStackPush((CURRENT_TOKEN.TOKEN_TYPE==TOKEN_TYPES.TK_TRUE ? 1 : 0).ToString());
  971. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  972. t = TYPE.Boolean;
  973. }
  974. //Negative Values
  975. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_MINUSOP)
  976. {
  977. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  978. t = Factor();
  979. runtimemod.CodeStackPush(OPCODES.OP_FNEG.ToString());
  980. }
  981. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_LARRAYBRACK)
  982. {
  983. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  984. }
  985. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_LPARENOP)
  986. {
  987. t = Expression();
  988. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RPARENOP)
  989. throw new TokenTypeMismatchException("Missing right paren");
  990. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  991. }
  992. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_STRING)
  993. {
  994. runtimemod.CodeStackPush(CURRENT_TOKEN.TOKEN_VALUE.ToString());
  995. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  996. t = TYPE.String;
  997. }
  998. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_NOT)
  999. {
  1000. CURRENT_TOKEN = Scanner.ScanAndRet(scan);
  1001. t = Factor();
  1002. runtimemod.CodeStackPush(OPCODES.OP_NOT.ToString());
  1003. }
  1004. else if (CURRENT_TOKEN.TOKEN_TYPE == TOKEN_TYPES.TK_LPARENOP)
  1005. {
  1006. t = Expression();
  1007. if (CURRENT_TOKEN.TOKEN_TYPE != TOKEN_TYPES.TK_RPARENOP)
  1008. throw new TokenTypeMismatchException("Missing close bracket.");
  1009. }
  1010. return t;
  1011. }
  1012. //----------------------EXPRESSION GRAMMAR----------------------------------
  1013. #endregion
  1014. //Var Exist - Check symbol table to see if variable exists
  1015. public bool VarExists(string token)
  1016. {
  1017. bool VariableExists = false;
  1018. //Create temporary stack to push values into
  1019. Stack<Dictionary<string, Record>> tempStack = new Stack<Dictionary<string, Record>>();
  1020. int STACK_COUNT = SYMBOL_TABLE_STACK.Count;
  1021. //cycle through the SYMBOL TABLE STACK
  1022. for (int i = 0; i < STACK_COUNT; i++)
  1023. {
  1024. //Create reference to top symbol table
  1025. Dictionary<string, Record> SymbTab = SYMBOL_TABLE_STACK.Pop();
  1026. //Check if variable exists in symbol table
  1027. if(!VariableExists)
  1028. VariableExists = SymbTab.ContainsKey(token);
  1029. //Push the stack we pop into symbol table
  1030. tempStack.Push(SymbTab);
  1031. }
  1032. //Pop all Symbol Tables back into the stack
  1033. for (int i = 0; i < STACK_COUNT; i++)
  1034. SYMBOL_TABLE_STACK.Push(tempStack.Pop());
  1035. return VariableExists;
  1036. }
  1037. //Keep popping symbol tables till we find the proper TK_VAR
  1038. //Do we need to implement code for multiple symbol tables???
  1039. //CHANGE as necessary
  1040. public bool Lookup(Token tt, ref int address, ref TYPE type)
  1041. {
  1042. /*Dictionary<string, Record> rec = SYMBOL_TABLE_STACK.Pop();
  1043. Record tempRec;
  1044. rec.TryGetValue(tt.VALUE, out tempRec);
  1045. if (tempRec!=null)
  1046. {
  1047. address = tempRec.address;
  1048. type = tempRec.TYPE;
  1049. SYMBOL_TABLE_STACK.Push(rec); // return it back
  1050. return true;
  1051. }
  1052. return false;*/
  1053. Record rec = new Record();
  1054. rec.TYPE_LT = TOKEN_TYPES.TK_ID;
  1055. Stack<Dictionary<string, Record>> tempStack = new Stack<Dictionary<string, Record>>();
  1056. bool found = false;
  1057. int STACK_COUNT = SYMBOL_TABLE_STACK.Count;
  1058. //return if the SYMBOL TABLE IS EMPTY
  1059. if (SYMBOL_TABLE_STACK.Count == 0)
  1060. return false;
  1061. while (SYMBOL_TABLE_STACK.Count != 0)
  1062. {
  1063. Dictionary<string, Record> symbolTable = SYMBOL_TABLE_STACK.Pop();
  1064. tempStack.Push(symbolTable);
  1065. foreach (KeyValuePair<string, Record> keyV in symbolTable)
  1066. if (keyV.Key == tt.VALUE)
  1067. {
  1068. rec = keyV.Value;
  1069. found = true;
  1070. }
  1071. }
  1072. //Pop SymbolTables back into the SYMBOL_TABLE_STACK
  1073. for (int i = 0; i < STACK_COUNT; i++)
  1074. SYMBOL_TABLE_STACK.Push(tempStack.Pop());
  1075. address = rec.address;

Large files files are truncated, but you can click here to view the full file