Advertisement
Guest User

Untitled

a guest
Sep 21st, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.76 KB | None | 0 0
  1. package ru.compscicenter.java2017.calculator;
  2.  
  3. import ru.compscicenter.java2017.calculator.Node.DigitNode;
  4. import ru.compscicenter.java2017.calculator.Node.Node;
  5. import ru.compscicenter.java2017.calculator.Node.NodeBuilder;
  6.  
  7. import java.rmi.UnexpectedException;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import java.util.regex.Pattern;
  11.  
  12. // Takes String to constructor and parses it into tree.
  13. // On calculate calcultes the result value from the contained tree.
  14. public class Calculator {
  15.  
  16. // Takes String and parses it with parse().
  17. public Calculator(String expression) throws UnexpectedException {
  18. root = parse(expression.replaceAll(" ", ""));
  19. }
  20.  
  21. // Returns result from the contained tree.
  22. public double calculate() {
  23. return root.getValue();
  24. }
  25.  
  26. private Node root;
  27.  
  28. // Parses given string into tree.
  29. private static Node parse(String expression) throws IllegalArgumentException, UnexpectedException {
  30. Node node;
  31.  
  32. // Trying to parse node as x+y+++ or x*y***.
  33. node = splitExpressionByDividers(expression, SplitExpressionHelper.getInstanceForAddition());
  34. if (node == null)
  35. node = splitExpressionByDividers(expression, SplitExpressionHelper.getInstanceForMultiplition());
  36. if (node != null)
  37. return node;
  38.  
  39. // In this blocks expression is tried to be matched with simple patterns.
  40. else if (bracketsPatter.matcher(expression).matches()) {
  41. return parse(expression.substring(1, expression.length() - 1));
  42. }
  43. else if (unaryPlusPattern.matcher(expression).matches()) {
  44. return parse(expression.substring(1));
  45. }
  46. else if (unaryMinusPattern.matcher(expression).matches()) {
  47. return NodeBuilder.buildUnaryMinusNode().setNode(parse(expression.substring(1)));
  48. }
  49. else if (exponentPattern.matcher(expression).matches()) {
  50. String[] splitMaster = expression.split("\\^");
  51. return NodeBuilder.buildExponentNode().setNodes(parse(splitMaster[0]),
  52. parse(splitMaster[1]));
  53. }
  54. else if (sinPattern.matcher(expression).matches()) {
  55. return NodeBuilder.buildSinNode().setNode(parse(expression.substring("sin(".length(), expression.length() - 1)));
  56. }
  57. else if (cosPattern.matcher(expression).matches()) {
  58. return NodeBuilder.buildCosNode().setNode(parse(expression.substring("cos(".length(), expression.length() - 1)));
  59. }
  60. else if (absPattern.matcher(expression).matches()) {
  61. return NodeBuilder.buildAbsNode().setNode(parse(expression.substring("abs(".length(), expression.length() - 1)));
  62. }
  63. else if (digitPattern.matcher(expression).matches()) {
  64. String[] splitMaster = expression.split("E");
  65. if (splitMaster.length == 1) {
  66. return NodeBuilder.buildDigitNode().setValue(Double.parseDouble(splitMaster[0]));
  67. }
  68. return NodeBuilder.buildDigitNode().setValue(Integer.parseInt(splitMaster[0]) * Math.pow(10, Integer.parseInt(splitMaster[1])));
  69. }
  70.  
  71. // If none of the patterns worked, then we do not know what we are dealing with.
  72. throw new UnexpectedException("Unknown problem while parsing: no matching pattern found!");
  73. }
  74.  
  75. // Parses expression into list of expressions and then forms them into Node.
  76. // Takes SplitExpressionHelper to know what binary operation we expect to parse.
  77. private static Node splitExpressionByDividers(String expression, SplitExpressionHelper helper) throws UnexpectedException {
  78. int bracketsCounter = 0;
  79. int lastAddedIndex = 0;
  80. List<String> splitedExpression = new ArrayList<>();
  81. List<Boolean> wasFirstDivider = new ArrayList<>();
  82.  
  83. // Dividing expression into list.
  84. for (int i = 1; i < expression.length(); ++i) {
  85. char symbol = expression.charAt(i);
  86. if (symbol == '(')
  87. bracketsCounter++;
  88. else if (symbol == ')') {
  89. if (bracketsCounter == 0)
  90. throw new IllegalArgumentException("Brackets don't match!");
  91. bracketsCounter--;
  92. }
  93. else if (symbol == helper.firstDivider && expression.charAt(i) != '(' && bracketsCounter == 0) {
  94. splitedExpression.add(expression.substring(lastAddedIndex, i));
  95. lastAddedIndex = i + 1;
  96. wasFirstDivider.add(true);
  97. }
  98. else if (symbol == helper.secondDivider && expression.charAt(i) != '(' && bracketsCounter == 0) {
  99. splitedExpression.add(expression.substring(lastAddedIndex, i));
  100. lastAddedIndex = i + 1;
  101. wasFirstDivider.add(false);
  102. }
  103. }
  104. splitedExpression.add(expression.substring(lastAddedIndex, expression.length()));
  105.  
  106. // This rule should always be true.
  107. assert splitedExpression.size() - 1 == wasFirstDivider.size();
  108.  
  109. // We recall what operation splited expression into list. Once we know we send it to the tree.
  110. if (splitedExpression.size() > 1) {
  111. Node lastNode;
  112. if (wasFirstDivider.get(0))
  113. lastNode = helper.getNodeFirstType().setNodes(parse(splitedExpression.get(0)), parse(splitedExpression.get(1)));
  114. else
  115. lastNode = helper.getNodeSecondType().setNodes(parse(splitedExpression.get(0)), parse(splitedExpression.get(1)));
  116. for (int i = 2; i < splitedExpression.size(); ++i) {
  117. if (wasFirstDivider.get(i - 1))
  118. lastNode = helper.getNodeFirstType().setNodes(lastNode, parse(splitedExpression.get(i)));
  119. else
  120. lastNode = helper.getNodeSecondType().setNodes(lastNode, parse(splitedExpression.get(i)));
  121. }
  122. return lastNode;
  123. }
  124.  
  125. // If we found no correct spliting in expression we return null to indicate that.
  126. return null;
  127. }
  128.  
  129. private static final Pattern bracketsPatter = Pattern.compile("\\(.*\\)");
  130. private static final Pattern unaryPlusPattern = Pattern.compile("\\+(((sin|cos|abs)?\\(.*\\))|([0-9]+(E(\\+|-)[0-9]*)?))");
  131. private static final Pattern unaryMinusPattern = Pattern.compile("-(((sin|cos|abs)?\\(.*\\))|([0-9]+(E(\\+|-)[0-9]*)?))");
  132. private static final Pattern sinPattern = Pattern.compile("sin\\(.*\\)");
  133. private static final Pattern cosPattern = Pattern.compile("cos\\(.*\\)");
  134. private static final Pattern absPattern = Pattern.compile("abs\\(.*\\)");
  135. private static final Pattern exponentPattern = Pattern.compile("(((sin|cos|abs)?\\(.*\\))|([0-9]+(E(\\+|-)[0-9]*)?))\\^(((sin|cos|abs)?\\(.*\\))|([0-9]+(E(\\+|-)[0-9]*)?))");
  136. private static final Pattern digitPattern = Pattern.compile("[0-9]+(E(\\+|-)[0-9]*)?");
  137. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement