All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kz.greetgo.scheduling.trigger.inner_logic.TriggerParserStructuring Maven / Gradle / Ivy

The newest version!
package kz.greetgo.scheduling.trigger.inner_logic;

import kz.greetgo.scheduling.trigger.TriggerParseError;

import java.util.ArrayList;
import java.util.List;

import static java.util.Objects.requireNonNull;

public class TriggerParserStructuring {

  private final Range top;
  private final String triggerString, topTriggerString;

  private TriggerParserStructuring(Range top, String triggerString) {
    this.top = top;
    this.triggerString = top.cut(triggerString);
    topTriggerString = triggerString;
  }

  public static TriggerParserStructuring of(Range top, String triggerString) {
    return new TriggerParserStructuring(top, triggerString);
  }

  enum TokenType {
    STR, PLUS, MUL, OPEN_BRACKET, CLOSE_BRACKET,
  }

  class Token {
    final TokenType type;
    final Range range;

    public Token(int from, int to, TokenType type) {
      requireNonNull(type);
      this.type = type;
      range = new Range(from, to);
    }

    public String source() {
      return range.cut(triggerString);
    }

    @Override
    public String toString() {
      return source();
    }
  }

  public final List tokens = new ArrayList<>();

  void makeTokens() {

    int prevIndex = 0;

    for (int index = 0; index < triggerString.length(); index++) {

      char c = triggerString.charAt(index);

      if (c == '*' || c == '+') {

        if (prevIndex != index) {
          if (triggerString.substring(prevIndex, index).trim().length() > 0) {
            tokens.add(new Token(prevIndex, index, TokenType.STR));
          }
        }

        tokens.add(new Token(index, index + 1, c == '*' ? TokenType.MUL : TokenType.PLUS));
        prevIndex = index + 1;

        continue;
      }

      if (c == '(' || c == ')') {

        if (prevIndex != index) {

          if (triggerString.substring(prevIndex, index).trim().length() > 0) {
            tokens.add(new Token(prevIndex, index, TokenType.STR));
          }

        }

        tokens.add(new Token(index, index + 1, c == '(' ? TokenType.OPEN_BRACKET : TokenType.CLOSE_BRACKET));
        prevIndex = index + 1;

      }

    }

    if (triggerString.substring(prevIndex).trim().length() > 0) {
      tokens.add(new Token(prevIndex, triggerString.length(), TokenType.STR));
    }

  }

  TriggerStruct triggerStruct;

  int tokenIndex = 0;

  void makeStruct() {
    tokenIndex = 0;
    triggerStruct = readStruct(null);
  }

  class Operation implements ExpressionElement {
    final Token token;

    public Operation(Token token) {
      this.token = token;
    }

    @Override
    public Range range() {
      return token.range;
    }
  }

  public final List parseErrors = new ArrayList<>();

  private TriggerStruct readStruct(Token openedBracket) {
    List elements = new ArrayList<>();

    while (true) {
      Token token = null;
      if (tokenIndex < tokens.size()) {
        token = tokens.get(tokenIndex++);
      }

      if (token == null) {
        return constructStruct(elements);
      }

      switch (token.type) {

        case CLOSE_BRACKET: {
          if (openedBracket == null) {
            parseErrors.add(new ParseError(token.range, "h56b4v6", "Несогласованная закрывающая скобка"));
          }
          return constructStruct(elements);
        }

        case OPEN_BRACKET:
          elements.add(readStruct(token));
          continue;

        case PLUS:
        case MUL:
          elements.add(new Operation(token));
          continue;

        case STR:
          elements.add(new TriggerStructStr(token.source(), token.range));
          continue;

        default:
          throw new RuntimeException("Unknown token.type = " + token.type);

      }
    }
  }

  private TriggerStruct constructStruct(List elements) {

    if (elements.isEmpty()) {
      parseErrors.add(new ParseError(new Range(0, 0), "UMBo7MopE4", "Нет данных"));
      return new TriggerStructEmpty();
    }

    TriggerStruct first;

    {
      ExpressionElement firstElement = elements.remove(0);
      if (firstElement instanceof Operation) {
        parseErrors.add(new ParseError(firstElement.range(), "Ka4zG7L9e1", "Нет данных"));
        return new TriggerStructEmpty();
      }
      first = (TriggerStruct) firstElement;
    }

    class Pair {
      final Operation operation;
      final TriggerStruct operand;

      public Pair(Operation operation, TriggerStruct operand) {
        this.operation = operation;
        this.operand = operand;
      }
    }

    List pairs = new ArrayList<>();

    Operation pre = null;
    for (ExpressionElement element : elements) {
      if (element instanceof Operation) {
        if (pre != null) {
          parseErrors.add(new ParseError(element.range(), "h4gh3vf", "Повторная операция"));
          return new TriggerStructEmpty();
        }
        pre = (Operation) element;
        continue;
      }

      TriggerStruct triggerStruct = (TriggerStruct) element;
      if (pre == null) {
        parseErrors.add(new ParseError(triggerStruct.range(), "5hb6267", "Отсутствует операция впереди"));
        return new TriggerStructEmpty();
      }
      pairs.add(new Pair(pre, triggerStruct));
      pre = null;
    }

    if (pre != null) {
      parseErrors.add(new ParseError(pre.range(), "33j5nb6", "Несогласованная операция"));
      return new TriggerStructEmpty();
    }


    TriggerStruct second = null;

    for (Pair pair : pairs) {

      switch (pair.operation.token.type) {

        case PLUS:
          if (second == null) {
            second = pair.operand;
          } else {
            first = new TriggerStructPlus(first, second);
            second = pair.operand;
          }
          continue;

        case MUL:
          if (second == null) {
            first = new TriggerStructMul(first, pair.operand);
          } else {
            second = new TriggerStructMul(second, pair.operand);
          }
          continue;

        default:
          throw new RuntimeException("Недопустимый тип : pair.operation.token.type = " + pair.operation.token.type);
      }

    }

    if (second != null) {
      first = new TriggerStructPlus(first, second);
    }

    return first;
  }

  public void makeResult() {

    makeTokens();
    makeStruct();

    errors = triggerStruct.errors(top, topTriggerString);
    result = triggerStruct.trigger();

  }

  public List errors;
  public Trigger result;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy