Guest User

Untitled

a guest
Oct 15th, 2018
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.82 KB | None | 0 0
  1. import java.util.LinkedList;
  2. import java.util.Queue;
  3. import java.util.Stack;
  4. import java.util.StringTokenizer;
  5.  
  6. // Copyright (c) 2018 Ryan Greene
  7. public class Parser {
  8.  
  9. private static Stack<ParseToken> stack;
  10. private static Queue<String> remainingTokens;
  11. private static final Runnable[][] table;
  12. private static final int[][] reductionTable;
  13. private static boolean accepted = false;
  14.  
  15. static {
  16. table = new Runnable[12][128];
  17. for (int state : new int[]{0, 4, 6, 7}) {
  18. table[state]['n'] = () -> shift(5);
  19. table[state]['('] = () -> shift(4);
  20. }
  21. table[1]['+'] = () -> shift(6);
  22. table[1]['-'] = () -> shift(6);
  23. table[1]['$'] = Parser::accept;
  24. for (char c : new char[]{'+', '-', ')', '$'})
  25. table[2][c] = () -> reduce('E', 'T');
  26. table[2]['*'] = () -> shift(7);
  27. table[2]['/'] = () -> shift(7);
  28. for (char c : new char[]{'+', '-', '*', '/', ')', '$'})
  29. table[3][c] = () -> reduce('T', 'F');
  30. for (char c : new char[]{'+', '-', '*', '/', ')', '$'})
  31. table[5][c] = () -> reduce('F', 'n');
  32. table[8]['+'] = () -> shift(6);
  33. table[8]['-'] = () -> shift(6);
  34. table[8][')'] = () -> shift(11);
  35. for (char c : new char[]{'+', '-', ')', '$'})
  36. table[9][c] = () -> reduce('E', 'E', 'T', '+', '-');
  37. table[9]['*'] = () -> shift(7);
  38. table[9]['/'] = () -> shift(7);
  39. for (char c : new char[]{'+', '-', '*', '/', ')', '$'})
  40. table[10][c] = () -> reduce('T', 'T', 'F', '*', '/');
  41. for (char c : new char[]{'+', '-', '*', '/', ')', '$'})
  42. table[11][c] = Parser::reduceParentheses;
  43.  
  44. reductionTable = new int[12][128];
  45. reductionTable[0]['E'] = 1;
  46. reductionTable[0]['T'] = 2;
  47. reductionTable[0]['F'] = 3;
  48. reductionTable[4]['E'] = 8;
  49. reductionTable[4]['T'] = 2;
  50. reductionTable[4]['F'] = 3;
  51. reductionTable[6]['T'] = 9;
  52. reductionTable[6]['F'] = 3;
  53. reductionTable[7]['F'] = 10;
  54. }
  55.  
  56. public static void main(String[] args) {
  57. try {
  58. System.out.println("Valid Expression = " + parse(args[0]) + ".");
  59. } catch (final Exception e) {
  60. System.out.println("Invalid Expression");
  61. }
  62. }
  63.  
  64. private static void shift(int state) {
  65. String token = remainingTokens.poll();
  66. int tokenValue = token.matches("\\d+") ? Integer.parseInt(token) : -1;
  67. stack.push(new ParseToken(tokenValue == -1 ? token.charAt(0) : 'n', state, tokenValue));
  68. print();
  69. }
  70.  
  71. private static void reduce(char to, char from) {
  72. ParseToken token = stack.pop();
  73. if (from != token.symbol)
  74. throw new IllegalStateException();
  75. int state = stack.peek().state;
  76. stack.push(new ParseToken(to, reductionTable[state][to], token.value));
  77. print();
  78. }
  79.  
  80. private static void reduce(char to, char operand1, char operand2, char operator1, char operator2) {
  81. ParseToken operandToke1 = stack.pop(), operatorToke = stack.pop(), operandToke2 = stack.pop();
  82. if (operatorToke.symbol != operator1 && operatorToke.symbol != operator2 || (operandToke1.value == -1
  83. || operandToke2.value == -1) || (operandToke2.symbol != operand1 || operandToke1.symbol != operand2))
  84. throw new IllegalStateException();
  85. int value = 0;
  86. if (operatorToke.symbol == '+')
  87. value = operandToke2.value + operandToke1.value;
  88. else if (operatorToke.symbol == '-')
  89. value = operandToke2.value - operandToke1.value;
  90. else if (operatorToke.symbol == '*')
  91. value = operandToke2.value * operandToke1.value;
  92. else if (operatorToke.symbol == '/')
  93. value = operandToke2.value / operandToke1.value;
  94. stack.push(new ParseToken(to, reductionTable[stack.peek().state][to], value));
  95. print();
  96. }
  97.  
  98. private static void reduceParentheses() {
  99. ParseToken rightParentheses = stack.pop(), eToken = stack.pop(), leftParentheses = stack.pop();
  100. if (leftParentheses.symbol != '(' || rightParentheses.symbol != ')' || eToken.symbol != 'E')
  101. throw new IllegalStateException();
  102. stack.push(new ParseToken('F', reductionTable[stack.peek().state]['F'], eToken.value));
  103. print();
  104. }
  105.  
  106. private static void accept() {
  107. if (stack.size() == 2 && remainingTokens.poll().equals("$"))
  108. accepted = true;
  109. else
  110. throw new IllegalStateException();
  111. }
  112.  
  113. private static void print() {
  114. stack.forEach(System.out::print);
  115. System.out.print("\t\t");
  116. remainingTokens.stream().map(t -> t + " ").forEach(System.out::print);
  117. System.out.println();
  118. }
  119.  
  120. private static int parse(String expression) {
  121. stack = new Stack<>();
  122. stack.push(new ParseToken('-', 0, -1));
  123.  
  124. remainingTokens = new LinkedList<>();
  125. StringTokenizer tokenizer = new StringTokenizer(expression.endsWith("$") ? expression : expression + "$",
  126. "+-*/()$", true);
  127. while (tokenizer.hasMoreTokens())
  128. remainingTokens.offer(tokenizer.nextToken());
  129.  
  130. accepted = false;
  131. while (!accepted) {
  132. String token = remainingTokens.peek();
  133. table[stack.peek().state][token.matches("\\d+") ? 'n' : token.charAt(0)].run();
  134. }
  135. return stack.pop().value;
  136. }
  137.  
  138. private static class ParseToken {
  139. final char symbol;
  140. final int state;
  141. final int value;
  142.  
  143. ParseToken(char symbol, int state, int value) {
  144. this.symbol = symbol;
  145. this.state = state;
  146. this.value = value;
  147. }
  148.  
  149. @Override
  150. public String toString() {
  151. return symbol == 'n' ? "[" + value + ":" + this.state + "]" : "[" + symbol + ":" + this.state + "]";
  152. }
  153. }
  154. }
Add Comment
Please, Sign In to add comment