С нуля написать компилятор (VI): Таблица управляемый синтаксический анализатор разбора его

Полный код проекта в C2j-компилятором

предисловие

Предыдущая информация официально завершила строительство и достаточное решение уменьшить конечный автомат, следующая задача состоит в том, чтобы заполнить таблицу синтаксического анализа на основе конечного автомата и синтаксического анализа осуществляется в соответствии с таблицей

уменьшить информацию

До завершения синтаксического анализа таблицы, есть еще последняя задача, которая описывает уменьшить информацию автоматически направлять машину, если выполняется снизить эксплуатационные

ProductionsStateNode уменьшить информацию в каждом узле завершена, в обход узла в производстве, если знак «» в конце выражения, то узел может быть получена на основе информации, выражения и уменьшить набор LookAhead, соответствующее выражению

уменьшить информацию, чтобы указать карту, ключевые символы могут быть выполнены, чтобы уменьшить, то есть в соответствии с наборами упреждающего, значение операции производства снижают

public HashMap<Integer, Integer> makeReduce() {
      HashMap<Integer, Integer> map = new HashMap<>();
      reduce(map, this.productions);
      reduce(map, this.mergedProduction);

      return map;
  }

  private void reduce(HashMap<Integer, Integer> map, ArrayList<Production> productions) {
      for (int i = 0; i < productions.size(); i++) {
          if (productions.get(i).canBeReduce()) {
              ArrayList<Integer> lookAhead = productions.get(i).getLookAheadSet();
              for (int j = 0; j < lookAhead.size(); j++) {
                  map.put(lookAhead.get(j), (productions.get(i).getProductionNum()));
              }
          }
      }
  }

Построение таблицы синтаксического анализа

Построение таблиц разбора, главным образом, в классе StateNodeManager, вы можете игнорировать логику loadTable и storageTableToFile этой части в основном хранить эту таблицу, можно использовать несколько раз

От основная логика начинается во время прохождения всех узлов, начинает прыгать информацию Карты по отношению к прыгать и прыгать узел назначения, то соответствующий (скачок от характера отношений является позицией начала маркеров перечисления ссылка) и копируется на другой узел назначения в карте. В соответствующей упреждающей выборке, поставленной перед затем уменьшить, чтобы получить информацию, символ найден, то его значение переписывается - (для операции производства уменьшить количество), причину отрицательного письменную, чтобы отличить операцию сдвига.

Поэтому HashMap <Целое число, HashMap <Целое, Целое >> эта структура данных представляет собой таблицу в качестве анализа:

  1. Первое число представляет текущий узел Integer
  2. Второе Целое число представляет входной символ
  3. Целое треть, больше 0, если операция сдвига сделана меньше 0 вы уменьшить операцию согласно деривации
public HashMap<Integer, HashMap<Integer, Integer>> getLrStateTable() {
      File table = new File("lrStateTable.sb");
      if (table.exists()) {
          return loadTable();
      }

      Iterator it;
      if (isTransitionTableCompressed) {
          it = compressedStateList.iterator();
      } else {
          it = stateList.iterator();
      }

      while (it.hasNext()) {
          ProductionsStateNode state = (ProductionsStateNode) it.next();
          HashMap<Integer, ProductionsStateNode> map = transitionMap.get(state);
          HashMap<Integer, Integer> jump = new HashMap<>();

          if (map != null) {
              for (Map.Entry<Integer, ProductionsStateNode> item : map.entrySet()) {
                  jump.put(item.getKey(), item.getValue().stateNum);
              }
          }

          HashMap<Integer, Integer> reduceMap = state.makeReduce();
          if (reduceMap.size() > 0) {
              for (Map.Entry<Integer, Integer> item : reduceMap.entrySet()) {

                  jump.put(item.getKey(), -(item.getValue()));
              }
          }

          lrStateTable.put(state.stateNum, jump);
      }

      storageTableToFile(lrStateTable);

      return lrStateTable;
  }

Табличной разборе

Основной процесс разбора класса LRStateTableParser, инициированный с помощью метода синтаксического анализа.

Второй и выступая в качестве необходимого стека ввода, узла стека, другой вещи, теперь нет необходимости использовать. При инициализации первого запуска узла в стек, текущих входном наборе символов EXT_DEF_LIST, а затем получить таблицу синтаксического анализа

public LRStateTableParser(Lexer lexer) {
    this.lexer = lexer;
    statusStack.push(0);
    valueStack.push(null);
    lexer.advance();
    lexerInput = Token.EXT_DEF_LIST.ordinal();
    lrStateTable = StateNodeManager.getInstance().getLrStateTable();
}

Синтаксические этапов:

  • Получить текущий символ в текущем узле и соответствующую операцию, т.е. действие> 0 является операция сдвига, действие <0 снизить операцию
  • Если ввести действие> 0, то есть операции сдвига
    1. Текущее состояние узла и ввод символов в стеке
    2. Здесь мы должны различать, если текущий символ является терминатором, на этот раз мы можем сразу прочитать следующий символ
    3. Однако, если есть не-терминальный символ, текущий символ должен быть использован, чтобы перейти непосредственно к следующему состоянию. Одно предостережение здесь является точкой, где текущие потребности нетерминала, помещаются рядом с соответствующим входным узлом в стеке, так, чтобы уменьшить, когда операция стеки поп-обратно символ является правильной
  • Если действие> 0, то есть, уменьшить эксплуатационные
    1. Для того, чтобы получить соответствующее производство
    2. Производство состояние узел, соответствующий правой части стека поп
    3. Полный уменьшить этот символ в стеке ввода
public void parse() {
      while (true) {
          Integer action = getAction(statusStack.peek(), lexerInput);

          if (action == null) {
              ConsoleDebugColor.outlnPurple("Shift for input: " + Token.values()[lexerInput].toString());
              System.err.println("The input is denied");
              return;
          }

          if (action > 0) {
              statusStack.push(action);
              text = lexer.text;

              // if (lexerInput == Token.RELOP.ordinal()) {
              //     relOperatorText = text;
              // }

              parseStack.push(lexerInput);

              if (Token.isTerminal(lexerInput)) {
                  ConsoleDebugColor.outlnPurple("Shift for input: " + Token.values()[lexerInput].toString() + "   text: " + text);

                  // Object obj = takeActionForShift(lexerInput);

                  lexer.advance();
                  lexerInput = lexer.lookAhead;
                  // valueStack.push(obj);
              } else {
                  lexerInput = lexer.lookAhead;
              }
          } else {
              if (action == 0) {
                  ConsoleDebugColor.outlnPurple("The input can be accepted");
                  return;
              }

              int reduceProduction = -action;
              Production product = ProductionManager.getInstance().getProductionByIndex(reduceProduction);
              ConsoleDebugColor.outlnPurple("reduce by product: ");
              product.debugPrint();

              // takeActionForReduce(reduceProduction);

              int rightSize = product.getRight().size();
              while (rightSize > 0) {
                  parseStack.pop();
                  // valueStack.pop();
                  statusStack.pop();
                  rightSize--;
              }

              lexerInput = product.getLeft();
              parseStack.push(lexerInput);
              // valueStack.push(attributeForParentNode);
          }
      }
  }

  private Integer getAction(Integer currentState, Integer currentInput) {
      HashMap<Integer, Integer> jump = lrStateTable.get(currentState);
      return jump.get(currentInput);
  }

Неоднозначность грамматики

А теперь завершила все синтаксический анализ контента, семантический анализ следует, но до того, что есть необходимость сказать, что наша текущая конструкция конечный автомат относится к (1) грамматики LALR, даже LALR (1) синтаксис достаточно сильный, но все же существуют LALR (1) грамматика не может справиться с синтаксисом, если данный вывод не соответствует, то конечный автомат еще не правильно решены, но синтаксис данного ранее в соответствии с LALR (1 ) синтаксис

резюме

Это является одним из основных

  • Конечный автомат и уменьшить информационную таблицу завершается разбор
  • Реализация таблицы с использованием синтаксиса синтаксического анализ таблицы управляемого разбора

рекомендация

отwww.cnblogs.com/secoding/p/11371502.html