Синтаксис языков программирования. Нисходящий синтаксический анализ, процедурная и автоматная реализации, страница 2

            Таблица 2. Часть управляющей таблицы автомата с одним состоянием

                        В управляющей таблице строки соответствуют верхнему элементу в стеке, а столбцы –               текущему входному символу. В управляющей таблице используются следующие обозначения:                         Push – положить в стек, Pop – снять верхний символ из стека, Next – прочитать следующий                                входной символ, Stop – останов по окончанию восстановления разбора правильного                                       предложения.

Программная реализация рекурсивного спуска:

//Part_6: синтаксический акцептор/анализатор

//Part_6_3: собственно восстановление дерева грамматического разбора

 public boolean parse(){

  if(la==null)return false;

  curWordIndex=getWordIndex();    //возьмем индекс первого терминала

  if(FirstOne())            //вызовем метод, разбирающий начальный нетерминал

   if(curWordIndex==0)         //если этот метод возвратил истину и весь входной поток прочитан

    return true;  //последовательность слов правильна, возвращаем истину

  return false;  //если что-то не так - вернем признак ошибки

 }

//все далее следующие методы:

//          - имеют имя нетерминала, разбором которого каждый из них занимается

//          - возвращают логическое значение

//          - содержат ровно столько последовательно выполняющихся блоков, сколько правил в грамматике есть для данного нетерминала

//          - каждый блок выполняется только при условии, что текущий терминал принадлежит множеству выбора донного правила

//          - внутри блока организована обработка правой части правила последовательно символ за символом слева направо;

//                     в зависимости от того, чем является каждый очередной символ, делается следующее:

//                     - для нетерминала - вызывается метод, имеющий его имя и, если от него получена ложь, то ложь возвращается выше;

//                     - для терминала - его индекс сравнивается с индексом текущего терминала, при несовпадении возвращается ложь (эта проверка не выполняется, если терминал есть первый символ правила),

//                       затем из входного потока читается следующий терминал; терминал указывается в примечании к оператору сравнения;

//                     - для действия - оно выполняется (пустая правая часть правила приравнивается к действию, для таких правил формируется {});

//                     если выполнена обработка всех символов правой части (и не была возвращена ложь), то возвращается истина

//          - если не будет выполнен ни один блок (текущий терминал не принадлежит множеству выбора ни одного правила) - возвращается значение ложь

 private boolean FirstOne(){cCnt+=1;

  if((curWordIndex>=0)&&SelSet[0].get(curWordIndex)){

   if(!objects())return false;

   return functions();

  }

  return false;

 }

 private boolean objects(){cCnt+=1;

  if((curWordIndex>=0)&&SelSet[1].get(curWordIndex)){

   curWordIndex=getWordIndex();

   if(curWordIndex!=1)return false;

   curWordIndex=getWordIndex();

   if(curWordIndex!=32)return false;

   curWordIndex=getWordIndex();

   if(!definitions())return false;

   if(curWordIndex!=33)return false;

   curWordIndex=getWordIndex();

   return objects();

  }

  if((curWordIndex>=0)&&SelSet[2].get(curWordIndex)){{}return true;

  }

  return false;

 }

 private boolean definitions(){cCnt+=1;

  if((curWordIndex>=0)&&SelSet[3].get(curWordIndex)){

   if(!type())return false;

   return restdef();

  }

  return false;

 }

 private boolean restdef(){cCnt+=1;

  if((curWordIndex>=0)&&SelSet[4].get(curWordIndex)){

   curWordIndex=getWordIndex();