Для хранения идентификаторов, констант и предопределённых слов языка используются хэш-таблицы идентификаторов, констант и предопределённых слов языка соответственно. Для каждого блока типа vars или do создаётся своя хэш-таблица идентификаторов, которая заносится в общую хэш-таблицу идентификаторов, в которой ключами являются имена блоков.
//временная таблица идентификатор одного блока
final Hashtable identHash = new Hashtable();
//таблица идентификаторов всех блоков
final Hashtable identTableBlock = new Hashtable();
//таблица констант
final Hashtable constHash = new Hashtable();
//таблица предопределенных слов языка
final Hashtable defHash = new Hashtable();
Таблицы имеют рандомизированную организацию. Занесение идентификаторов и констант в соответствующие таблицы производится с помощью действий включённых в систему регулярных выражений.
Для целых констант:
if(my.GTNB() == false){if(constHash.get(Lexem.textOfWord.toString()) == null)
{Lexem.wordIndex = constCnt++; constHash.put(Lexem.textOfWord.toString(),Lexem);}}
Для вещественных констант:
if(constHash.get(Lexem.textOfWord.toString()) == null)
{Lexem.wordIndex = constCnt++; constHash.put(Lexem.textOfWord.toString(),Lexem);}
Для идентификаторов:
if(my.GTNB() == false){if(identHash.get(Lexem.textOfWord.toString()) == null && defHash.get(Lexem.textOfWord.toString()) == null)
{Lexem.wordIndex = my.GetCnt(); my.IncCnt(); identHash.put(Lexem.textOfWord.toString(),Lexem);}}
По завершению проверки очередного блока, созданная для него таблица идентификаторов по ключу-имени блока заносится в общую таблицу идентификаторов:
identTableBlock.put(NameBlock.get(NameBlock.size()-1),identHash.clone());identHash.clear();
В классе лексического анализатора определён счётчик констант:
//счетчик констант
int constCnt = 0;
Счётчик идентификаторов определён в моём классе, так как он используется как лексическим, так и синтаксическим анализаторами. В этом же классе определены два флага. Один из них используется для не занесения имен блоков и данных из блоков связей в таблицы идентификаторов. Класс приведён ниже:
//мой класс
class MyClass{
private boolean ThisNameBlock;
private boolean ThisOnlyIdent;
private int identCnt;
public MyClass()
{
//флаг для не занесения имени блока к таблицу идентификаторов и констант
ThisNameBlock = false;
//флаг для определения, имеется в операторе присваивания единичный идентификатор или выражение(используется для проверке недопустимости присваивания переменной самой себе)
ThisOnlyIdent = true;
//счетчик идентификаторов
identCnt=0;
}
public void TNBT(){ ThisNameBlock=true; }
public void TNBF(){ ThisNameBlock=false; }
public boolean GTNB () { return ThisNameBlock; }
public void TOIT(){ ThisOnlyIdent=true; }
public void TOIF(){ ThisOnlyIdent=false; }
public boolean GTOI () { return ThisOnlyIdent; }
public void IncCnt(){ identCnt=identCnt+1; }
public int GetCnt () { return identCnt; }
}
Формирование таблицы предопределённых слов происходит на этапе восстановления дерева грамматического разбора. В функцию parse для этого вносится следующее:
// занесение предопределенных слов в таблицу предопределенных слов
int i=0;
for(; i<words.length; i++)
defHash.put(words[i], new Integer(i));
Ключом для помещение новых значений в таблицы является текстовое представление идентификаторов, констант и предопределённых слов. По ключу в таблицы помещаются порядковые номера новых элементов таблиц. Порядковый номер соответствует индексу данного слова в группе идентификаторов, констант или предопределённых слов. Ключ и индекс слова в группе и образуют лексему.
Так как идентификаторы являются переменными, то в дальнейшем с каждым идентификатором придется связать его значение. Для этого используется таблица значений ResultHash, в которую заносятся значения переменных по индексу слова в группе.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.