Java IRC bot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Parser.java 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * To change this template, choose Tools | Templates
  3. * and open the template in the editor.
  4. */
  5. package com.dmdirc.addons.calc;
  6. import java.text.ParseException;
  7. import java.util.ArrayList;
  8. import java.util.Arrays;
  9. import java.util.Collections;
  10. import java.util.Comparator;
  11. import java.util.List;
  12. /**
  13. *
  14. * @author chris
  15. */
  16. public class Parser {
  17. protected final Lexer lexer;
  18. protected static final List<TokenType> TOKENS_BY_PRECEDENCE;
  19. static {
  20. TOKENS_BY_PRECEDENCE = new ArrayList<TokenType>(Arrays.asList(TokenType.values()));
  21. Collections.sort(TOKENS_BY_PRECEDENCE, new TokenTypePrecedenceComparator());
  22. }
  23. public Parser(Lexer lexer) {
  24. this.lexer = lexer;
  25. }
  26. public TreeToken parse() throws ParseException {
  27. final List<TreeToken> tokens = new ArrayList<TreeToken>();
  28. for (Token token : lexer.tokenise()) {
  29. tokens.add(new TreeToken(token));
  30. }
  31. return parse(tokens);
  32. }
  33. protected TreeToken parse(final List<TreeToken> tokens) throws ParseException {
  34. System.out.println("Parse: " + Arrays.toString(tokens.toArray()));
  35. while (tokens.size() > 1) {
  36. System.out.println(" --> " + Arrays.toString(tokens.toArray()));
  37. for (TokenType type : TOKENS_BY_PRECEDENCE) {
  38. final int offset = findTokenType(tokens, type);
  39. if (offset > -1) {
  40. System.out.println(" --> Found token " + type);
  41. switch (type.getArity()) {
  42. case HIDDEN:
  43. parseHiddenOperator(tokens, offset);
  44. break;
  45. case BINARY:
  46. parseBinaryOperator(tokens, offset);
  47. break;
  48. case UNARY:
  49. parseUnaryOperator(tokens, offset);
  50. break;
  51. case NULLARY:
  52. parseNullaryOperator(tokens, offset);
  53. break;
  54. }
  55. break;
  56. }
  57. }
  58. }
  59. return tokens.get(0);
  60. }
  61. protected void parseNullaryOperator(final List<TreeToken> tokens, final int offset)
  62. throws ParseException {
  63. if (tokens.get(offset).getToken().getType() == TokenType.BRACKET_CLOSE
  64. || tokens.get(offset).getToken().getType() == TokenType.BRACKET_OPEN) {
  65. parseBracket(tokens, offset);
  66. } else {
  67. parseNumber(tokens, offset);
  68. }
  69. }
  70. protected void parseBracket(final List<TreeToken> tokens, final int offset)
  71. throws ParseException {
  72. final List<TreeToken> stack = new ArrayList<TreeToken>();
  73. System.out.println("ParseBracket: " + offset + " " + Arrays.toString(tokens.toArray()));
  74. for (int i = offset - 1; i > 0; i--) {
  75. if (tokens.get(i).getToken().getType() == TokenType.BRACKET_OPEN
  76. && !tokens.get(i).isProcessed()) {
  77. System.out.println("Found opening bracket at index " + i);
  78. tokens.add(i, parse(stack));
  79. tokens.get(i).setProcessed();
  80. tokens.remove(i + 1);
  81. tokens.remove(i + 1);
  82. return;
  83. } else {
  84. System.out.println("Skipping " + tokens.get(i));
  85. stack.add(0, tokens.get(i));
  86. tokens.remove(i);
  87. }
  88. }
  89. throw new ParseException("Couldn't find matching opening bracket", offset);
  90. }
  91. protected void parseBinaryOperator(final List<TreeToken> tokens, final int offset) {
  92. tokens.get(offset).addChild(tokens.get(offset - 1));
  93. tokens.get(offset).addChild(tokens.get(offset + 1));
  94. tokens.get(offset).setProcessed();
  95. tokens.remove(offset + 1);
  96. tokens.remove(offset - 1);
  97. }
  98. protected void parseUnaryOperator(final List<TreeToken> tokens, final int offset) {
  99. tokens.get(offset).addChild(tokens.get(offset + 1));
  100. tokens.get(offset).setProcessed();
  101. tokens.remove(offset + 1);
  102. }
  103. protected void parseHiddenOperator(final List<TreeToken> tokens, final int offset) {
  104. tokens.remove(offset);
  105. }
  106. protected void parseNumber(final List<TreeToken> tokens, final int offset) {
  107. tokens.get(offset).setProcessed();
  108. }
  109. protected static int findTokenType(final List<TreeToken> tokens, final TokenType type) {
  110. for (int i = 0; i < tokens.size(); i++) {
  111. if (tokens.get(i).getToken().getType() == type && !tokens.get(i).isProcessed()) {
  112. return i;
  113. }
  114. }
  115. return -1;
  116. }
  117. protected static class TokenTypePrecedenceComparator implements Comparator<TokenType> {
  118. @Override
  119. public int compare(TokenType o1, TokenType o2) {
  120. return o2.getPrecedence() - o1.getPrecedence();
  121. }
  122. }
  123. }