PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/ILCalc/Parser/Parser.cs

#
C# | 211 lines | 148 code | 38 blank | 25 comment | 43 complexity | 10c3f1be73449dc7c3718c87dac7f36b MD5 | raw file
Possible License(s): LGPL-2.1
  1. using System;
  2. using System.Collections.Generic;
  3. namespace ILCalc
  4. {
  5. sealed partial class Parser<T>
  6. {
  7. #region Fields
  8. int exprDepth, curPos, prePos;
  9. Stack<Code> curStack;
  10. T value;
  11. #endregion
  12. int Parse(ref int i, bool func)
  13. {
  14. Item prev = Item.Begin;
  15. int separators = 0;
  16. var operators = new Stack<Code>();
  17. this.curStack = operators;
  18. while (i < this.expr.Length)
  19. {
  20. char c = this.expr[i];
  21. if (Char.IsWhiteSpace(c)) { i++; continue; }
  22. this.curPos = i++;
  23. int val;
  24. // ============================================= NUMBER ==
  25. if ((val = Literal.TryParse(i-1, this)) != -1)
  26. {
  27. i += val - 1;
  28. // [ )123 ], [ 123 456 ] or [ pi123 ]
  29. if (prev >= Item.Number)
  30. {
  31. throw IncorrectConstr(prev, Item.Number, i);
  32. }
  33. Output.PutConstant(value);
  34. prev = Item.Number;
  35. }
  36. // =========================================== OPERATOR ==
  37. else if ((val = Operators.IndexOf(c)) != -1)
  38. {
  39. // BINARY ======================
  40. // [ )+ ], [ 123+ ] or [ pi+ ]
  41. if (prev >= Item.Number)
  42. {
  43. Flush(operators, Priority[val]);
  44. operators.Push((Code) val);
  45. }
  46. // UNARY [-] ===================
  47. else if (val == (int) Code.Sub)
  48. {
  49. // prev == [+-], [,] or [(]
  50. operators.Push(Code.Neg);
  51. }
  52. // UNARY [+] ===================
  53. else
  54. {
  55. throw IncorrectConstr(prev, Item.Operator, i);
  56. }
  57. //i++; // <===
  58. prev = Item.Operator;
  59. }
  60. // ========================================== SEPARATOR ==
  61. else if (c == this.sepSymbol)
  62. {
  63. if (!func)
  64. {
  65. throw InvalidSeparator();
  66. }
  67. // [ (, ], [ +, ] or [ ,, ]
  68. if (prev <= Item.Begin)
  69. {
  70. throw IncorrectConstr(prev, Item.Separator, i);
  71. }
  72. Flush(operators);
  73. Output.PutSeparator();
  74. separators++;
  75. //i++; // <====
  76. prev = Item.Separator;
  77. }
  78. // ========================================= BRACE OPEN ==
  79. else if (c == '(')
  80. {
  81. // [ )( ], [ 123( ] or [ pi( ]
  82. if (prev >= Item.Number)
  83. {
  84. if (!Context.ImplicitMul)
  85. {
  86. throw IncorrectConstr(prev, Item.Begin, i);
  87. }
  88. Flush(operators, 1);
  89. operators.Push(Code.Mul); // Insert [*]
  90. }
  91. //i++; // <======
  92. ParseNested(ref i, false);
  93. this.curStack = operators;
  94. prev = Item.End;
  95. }
  96. // ======================================== BRACE CLOSE ==
  97. else if (c == ')')
  98. {
  99. // [ +) ], [ ,) ] or [ () ]
  100. if (prev <= Item.Separator ||
  101. (!func && prev == Item.Begin))
  102. {
  103. throw IncorrectConstr(prev, Item.End, i);
  104. }
  105. Flush(operators);
  106. if (this.exprDepth == 0)
  107. {
  108. throw BraceDisbalance(this.curPos, true);
  109. }
  110. if (prev != Item.Begin)
  111. {
  112. separators++;
  113. }
  114. //i++; // <=====
  115. return separators;
  116. }
  117. // ========================================= IDENTIFIER ==
  118. else if (Char.IsLetter(c) || c == '_')
  119. {
  120. if (prev >= Item.Number)
  121. {
  122. // [ pi sin ]
  123. if (prev == Item.Identifier)
  124. {
  125. //TODO: test if "sin z" (1 char unresolved!)
  126. throw IncorrectIden(i);
  127. }
  128. if (!Context.ImplicitMul)
  129. {
  130. throw IncorrectConstr(prev, Item.Identifier, i);
  131. }
  132. // [ )pi ] or [ 123pi ]
  133. Flush(operators, 1);
  134. operators.Push(Code.Mul); // Insert [*]
  135. }
  136. prev = ScanIdenifier(ref i);
  137. }
  138. // ========================================= UNRESOLVED ==
  139. else
  140. {
  141. throw UnresolvedSymbol(this.curPos);
  142. }
  143. this.prePos = this.curPos;
  144. }
  145. // ====================================== END OF EXPRESSION ==
  146. // [ +) ], [ ,) ] or [ () ]
  147. if (prev <= Item.Begin)
  148. {
  149. throw IncorrectConstr(prev, Item.End, i);
  150. }
  151. Flush(operators);
  152. Output.PutExprEnd();
  153. return -1;
  154. }
  155. #region Stack Operations
  156. void Flush(Stack<Code> stack)
  157. {
  158. while (stack.Count > 0)
  159. {
  160. Output.PutOperator(stack.Pop());
  161. }
  162. }
  163. void Flush(Stack<Code> stack, int priority)
  164. {
  165. while (stack.Count > 0 &&
  166. priority <= Priority[(int) stack.Peek()])
  167. {
  168. Output.PutOperator(stack.Pop());
  169. }
  170. }
  171. #endregion
  172. }
  173. }