PageRenderTime 42ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/src/frontend/pascal/parsers/ExpressionParser.cs

http://github.com/dfdemar/Pascal_Interpreter
C# | 265 lines | 191 code | 51 blank | 23 comment | 14 complexity | 6a21f0d00c4dece0bd431f3a8faca567 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Interpreter.intermediate;
  6. using Interpreter.intermediate.ICodeImplementation;
  7. using Interpreter.intermediate.SymbolTableImplementation;
  8. namespace Interpreter.frontend.pascal.parsers
  9. {
  10. public class ExpressionParser : StatementParser
  11. {
  12. private static readonly List<PascalTokenType> REL_OPS = new List<PascalTokenType>();
  13. private static readonly List<PascalTokenType> ADD_OPS = new List<PascalTokenType>();
  14. private static readonly List<PascalTokenType> MULT_OPS = new List<PascalTokenType>();
  15. private static readonly Dictionary<PascalTokenType, ICodeNodeType> REL_OPS_MAP = new Dictionary<PascalTokenType, ICodeNodeType>();
  16. private static readonly Dictionary<PascalTokenType, ICodeNodeTypeImplementation> ADD_OPS_OPS_MAP = new Dictionary<PascalTokenType, ICodeNodeTypeImplementation>();
  17. private static readonly Dictionary<PascalTokenType, ICodeNodeType> MULT_OPS_OPS_MAP = new Dictionary<PascalTokenType, ICodeNodeType>();
  18. public ExpressionParser(PascalParserTD parent) : base(parent)
  19. {
  20. }
  21. static ExpressionParser()
  22. {
  23. REL_OPS.Add(PascalTokenType.EQUALS);
  24. REL_OPS.Add(PascalTokenType.NOT_EQUALS);
  25. REL_OPS.Add(PascalTokenType.LESS_THAN);
  26. REL_OPS.Add(PascalTokenType.LESS_EQUALS);
  27. REL_OPS.Add(PascalTokenType.GREATER_THAN);
  28. REL_OPS.Add(PascalTokenType.GREATER_EQUALS);
  29. ADD_OPS.Add(PascalTokenType.PLUS);
  30. ADD_OPS.Add(PascalTokenType.MINUS);
  31. ADD_OPS.Add(PascalTokenType.OR);
  32. MULT_OPS.Add(PascalTokenType.STAR);
  33. MULT_OPS.Add(PascalTokenType.SLASH);
  34. MULT_OPS.Add(PascalTokenType.DIV);
  35. MULT_OPS.Add(PascalTokenType.MOD);
  36. MULT_OPS.Add(PascalTokenType.AND);
  37. REL_OPS_MAP.Add(PascalTokenType.EQUALS, ICodeNodeTypeImplementation.EQ);
  38. REL_OPS_MAP.Add(PascalTokenType.NOT_EQUALS, ICodeNodeTypeImplementation.NE);
  39. REL_OPS_MAP.Add(PascalTokenType.LESS_THAN, ICodeNodeTypeImplementation.LT);
  40. REL_OPS_MAP.Add(PascalTokenType.LESS_EQUALS, ICodeNodeTypeImplementation.LE);
  41. REL_OPS_MAP.Add(PascalTokenType.GREATER_THAN, ICodeNodeTypeImplementation.GT);
  42. REL_OPS_MAP.Add(PascalTokenType.GREATER_EQUALS, ICodeNodeTypeImplementation.GE);
  43. ADD_OPS_OPS_MAP.Add(PascalTokenType.PLUS, ICodeNodeTypeImplementation.ADD);
  44. ADD_OPS_OPS_MAP.Add(PascalTokenType.MINUS, ICodeNodeTypeImplementation.SUBTRACT);
  45. ADD_OPS_OPS_MAP.Add(PascalTokenType.OR, ICodeNodeTypeImplementation.OR);
  46. MULT_OPS_OPS_MAP.Add(PascalTokenType.STAR, ICodeNodeTypeImplementation.MULTIPLY);
  47. MULT_OPS_OPS_MAP.Add(PascalTokenType.SLASH, ICodeNodeTypeImplementation.FLOAT_DIVIDE);
  48. MULT_OPS_OPS_MAP.Add(PascalTokenType.DIV, ICodeNodeTypeImplementation.INTEGER_DIVIDE);
  49. MULT_OPS_OPS_MAP.Add(PascalTokenType.MOD, ICodeNodeTypeImplementation.MOD);
  50. MULT_OPS_OPS_MAP.Add(PascalTokenType.AND, ICodeNodeTypeImplementation.AND);
  51. }
  52. public override ICodeNode Parse(Token token)
  53. {
  54. return ParseExpression(token);
  55. }
  56. private ICodeNode ParseExpression(Token token)
  57. {
  58. ICodeNode rootNode = ParseSimpleExpression(token);
  59. token = CurrentToken();
  60. PascalTokenType tokenType = (PascalTokenType)token.type; // TokenType in original Java
  61. // Look for relational operator
  62. if (REL_OPS.Contains(tokenType))
  63. {
  64. // Create a new operator node and adopt the current tree as its first child.
  65. ICodeNodeType nodeType = REL_OPS_MAP[tokenType];
  66. ICodeNode opNode = ICodeFactory.CreateICodeNode(nodeType);
  67. opNode.AddChild(rootNode);
  68. token = NextToken();
  69. opNode.AddChild(ParseSimpleExpression(token));
  70. rootNode = opNode;
  71. }
  72. return rootNode;
  73. }
  74. private ICodeNode ParseSimpleExpression(Token token)
  75. {
  76. TokenType signType = null; // type of leading sign (if any)
  77. // Look for a leading + or - sign.
  78. TokenType tokenType = token.type;
  79. if ((tokenType == PascalTokenType.PLUS) || (tokenType == PascalTokenType.MINUS))
  80. {
  81. signType = tokenType;
  82. token = NextToken(); // consume the + or -
  83. }
  84. // Parse a term and make the root of its tree the root node.
  85. ICodeNode rootNode = ParseTerm(token);
  86. // Was there a leading - sign?
  87. if (signType == PascalTokenType.MINUS)
  88. {
  89. // Create a NEGATE node and adopt the current tree
  90. // as its child. The NEGATE node becomes the new root node.
  91. ICodeNode negateNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.NEGATE);
  92. negateNode.AddChild(rootNode);
  93. rootNode = negateNode;
  94. }
  95. token = CurrentToken();
  96. tokenType = token.type;
  97. // Loop over additive operators.
  98. while (ADD_OPS.Contains(tokenType))
  99. {
  100. // Create a new operator node and adopt the current tree
  101. // as its first child.
  102. ICodeNodeType nodeType = ADD_OPS_OPS_MAP[(PascalTokenType)tokenType];
  103. ICodeNode opNode = ICodeFactory.CreateICodeNode(nodeType);
  104. opNode.AddChild(rootNode);
  105. token = NextToken(); // consume the operator
  106. // Parse another term. The operator node adopts
  107. // the term's tree as its second child.
  108. opNode.AddChild(ParseTerm(token));
  109. // The operator node becomes the new root node.
  110. rootNode = opNode;
  111. token = CurrentToken();
  112. tokenType = token.type;
  113. }
  114. return rootNode;
  115. }
  116. private ICodeNode ParseTerm(Token token)
  117. {
  118. ICodeNode rootNode = ParseFactor(token);
  119. token = CurrentToken();
  120. TokenType tokenType = token.type;
  121. while (MULT_OPS.Contains(tokenType))
  122. {
  123. ICodeNodeType nodeType = MULT_OPS_OPS_MAP[(PascalTokenType)tokenType];
  124. ICodeNode opNode = ICodeFactory.CreateICodeNode(nodeType);
  125. opNode.AddChild(rootNode);
  126. token = NextToken(); // consume the operator
  127. opNode.AddChild(ParseFactor(token));
  128. rootNode = opNode;
  129. token = CurrentToken();
  130. tokenType = token.type;
  131. }
  132. return rootNode;
  133. }
  134. private ICodeNode ParseFactor(Token token)
  135. {
  136. TokenType tokenType = token.type;
  137. ICodeNode rootNode = null;
  138. switch (tokenType.ToString())
  139. {
  140. case "IDENTIFIER":
  141. {
  142. // Look up the identifier in the symbol table stack.
  143. // Flag the identifier as undefined if it's not found.
  144. String name = token.text.ToLower();
  145. SymbolTableEntry id = symbolTableStack.Lookup(name);
  146. if (id == null)
  147. {
  148. errorHandler.flag(token, PascalErrorCode.IDENTIFIER_UNDEFINED, this);
  149. id = symbolTableStack.EnterLocal(name);
  150. }
  151. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.VARIABLE);
  152. rootNode.SetAttribute(ICodeKeyImplementation.ID, id);
  153. id.AppendLineNumber(token.lineNumber);
  154. token = NextToken(); // consume the identifier
  155. break;
  156. }
  157. case "INTEGER":
  158. {
  159. // Create an INTEGER_CONSTANT node as the root node.
  160. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.INTEGER_CONSTANT);
  161. rootNode.SetAttribute(ICodeKeyImplementation.VALUE, token.value);
  162. token = NextToken(); // consume the number
  163. break;
  164. }
  165. case "REAL":
  166. {
  167. // Create an REAL_CONSTANT node as the root node.
  168. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.REAL_CONSTANT);
  169. rootNode.SetAttribute(ICodeKeyImplementation.VALUE, token.value);
  170. token = NextToken(); // consume the number
  171. break;
  172. }
  173. case "STRING":
  174. {
  175. String value = (String) token.value;
  176. // Create a STRING_CONSTANT node as the root node.
  177. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.STRING_CONSTANT);
  178. rootNode.SetAttribute(ICodeKeyImplementation.VALUE, value);
  179. token = NextToken(); // consume the string
  180. break;
  181. }
  182. case "NOT":
  183. {
  184. token = NextToken(); // consume the NOT
  185. // Create a NOT node as the root node.
  186. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.NOT);
  187. // Parse the factor. The NOT node adopts the
  188. // factor node as its child.
  189. rootNode.AddChild(ParseFactor(token));
  190. break;
  191. }
  192. case "LEFT_PAREN":
  193. {
  194. token = NextToken(); // consume the (
  195. // Parse an expression and make its node the root node.
  196. rootNode = ParseExpression(token);
  197. // Look for the matching ) token.
  198. token = CurrentToken();
  199. if (token.type == PascalTokenType.RIGHT_PAREN)
  200. token = NextToken(); // consume the )
  201. else
  202. errorHandler.flag(token, PascalErrorCode.MISSING_RIGHT_PAREN, this);
  203. break;
  204. }
  205. default:
  206. {
  207. errorHandler.flag(token, PascalErrorCode.UNEXPECTED_TOKEN, this);
  208. break;
  209. }
  210. }
  211. return rootNode;
  212. }
  213. }
  214. }