3468
.pdfДействия с идентификатором на различных фазах трансляции представлены в табл. 9.
|
|
Таблица 9 |
|
Действия с идентификатором |
|
Фаза компиляции |
Действие с идентификатором |
|
|
|
|
1. |
Лексический анализ |
выделение |
|
|
|
2. |
Синтаксический разбор |
|
|
|
|
3. |
Семантический анализ |
определение характеристик |
|
|
|
4. |
Подготовка к генерации кода |
|
|
|
|
В компиляторах используются специальные хранилища данных, называемые таблицами идентификаторов.
Компилятор может работать с одной или несколькими таблицам идентификаторов - их количество зависит от реализации компилятора.
Информация, хранящаяся в таблицах идентификато-
ров (пример)
1.Для переменных:
имя переменной;
тип данных переменной;
область памяти, связанная с переменной.
2.Для констант:
название константы (если оно имеется);
значение константы;
тип данных константы (если требуется).
3.Для функций:
имя функции;
количество и типы формальных аргументов функции;
201
тип возвращаемого результата;
адрес кода функции.
Принцип работы компилятора с таблицей идентифи-
каторов: на различных фазах компиляции он вынужден многократно обращаться к таблице для
поиска информации,
записи новых данных.
Задание. Разработать программу, выполняющую следующие функции:
открывать и загружать файл с кодом программы (*.txt,
или *.pas, или *.cs и т.п.);
разбирать на лексемы строки кода, составленные на любом языке программирования;
строить таблицу идентификаторов следующего вида: имя, тип, признак (переменная, константа, процедура или функция).
Пример листинга программы:
//Основное окно программы Form1 using System;
using System.Collections.Generic; using System.Collections;
using System.ComponentModel; using System.Data;
using System.Drawing; using System.Linq; using System.Text;
using System.Windows.Forms; using System.IO;
namespace spo2_1
202
{
public partial class Form1 : Form
{
FileStream FS; bool find;
//список ключевых слов
string[] keyword = { "uint", "int", "string", "char", "long", "ulong","bool" };
string[] str;
//массив для хранения элементов таблицы идентификаторов
ArrayList al = new ArrayList();
public Form1()
{
InitializeComponent();
}
//обработка откратия файла
private void button1_Click(object sender, EventArgs e)
{
//переменная для хранения имени файла string s;
//расширения выбираемых в диалоге файлов openFileDialog1.Filter = "txt files (*.txt)|*.txt|cs files
(*.cs)|*.cs|All files (*.*)|*.*";
if (openFileDialog1.ShowDialog() == DialogResult.OK) { s = openFileDialog1.FileName;}
else
{
return;
}
try
{
203
//открытие потока для считывания файла
FS = File.Open(s, FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(FS);
//всё содержимое файла записывается в переменную
str
string str = reader.ReadToEnd(); richTextBox1.Text = str;
//разбиваем текст по переходу на новую строку string[] fields = str.Split('\n');
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show("Невозможно открыть файл"); throw;
}
finally
{
FS.Close();
}
}
//обработка нажатия кнопки "проанализировать" private void button2_Click(object sender, EventArgs e)
{
//очищаем массив элементов таблицы идентификаторов al.Clear();
//очищаем окно richTextBox2.Text = ""; find = true;
string text = richTextBox1.Text;
204
//разбиваем текст по символам ";" "{" "(" str = text.Split(';','{','(');
//и анализируем каждую полученную строку for (int i = 0; i < str.Length; i++)
{
//разбиваем строку на слова разделенные пробелом string[] leks = str[i].Split(' ');
//анализируем каждое слово for (int j = 0; j < leks.Length; j++)
{
//переменная используется из-за особенностей синтаксиса програмных функций
if (find == true)
{
//ищем идентификаторы по ключевым словам //если найдено слово "void" то идентификатор
- процедура
if (leks[j] == "void")
{
element el = new element(); el.F = "процедура"; el.Type = leks[j];
//если это не функция, тогда получаем имя
процедуры
if (leks[j + 1] != "(") el.Name = leks[j + 1];
//и добавляем полученный элемент в массив идентификаторов
al.Add(el);
break;
}
//если найдено ключевое слово для константы получаем её имя и тип
205
if (leks[j] == "const")
{
element el = new element(); el.F = "константа"; el.Type = leks[j + 1];
if (leks[j + 2] != "[") el.Name = leks[j + 2];
break;
}
//проверяем список ключевых слов для стандартных типов переменных
for (int k = 0; k < keyword.Length; k++)
{
if (leks[j] == keyword[k])
{
element el = new element();
//и определяем является ли это обычной
переменной
if (leks[j + 1] != "[]" && leks[j + 1] != "(")
{
el.F = "переменная"; el.Name = leks[j + 1];
}
//массивом
if (leks[j + 1] == "[]")
{
el.F = "массив"; el.Name = leks[j + 2];
}
//или функцией el.Type = leks[j];
if (j + 2 < leks.Length)
206
{
if (leks[j + 2] == "(") el.F = "функция";
find = false;
}
//также добавляем элемент в массив содержащий все идентификатоы
al.Add(el);
break;
}
}
}
}
find = true;
}
//проверяем полученный массив на наличие повторных записей одной и той же переменной
for (int k = 0; k < al.Count; k++)
{
for (int k2 = k+1; k2 < al.Count; k2++)
{
//если имя и тип двух элементов массива
совпадают
if (((element)al[k]).Name == ((element)al[k2]).Name && ((element)al[k]).Type == ((element)al[k2]).Type)
{
//удаляем второй элемент из массива al.Remove(al[k2]);
}
}
}
207
//выводим все элементы массива на экран foreach (element el in al)
{
richTextBox2.Text += el.ToString();
}
}
}
}
//класс element.cs using System;
using System.Collections.Generic; using System.Linq;
using System.Text;
//Класс позволяет создать элементы таблицы идентификаторов //содержит поля имя, тип, и признак //а также методы, которые позволяют задать и получить значения //полей данного класса
namespace spo2_1
{
class element
{
string name; string type; string f;
public element()
{
}
public string Name
{
get
208
{
return name;
}
set
{
name = value;
}
}
public string Type
{
get
{
return type;
}
set
{
type = value;
}
}
public string F
{
get
{
return f;
}
set
{
f = value;
}
}
public override string ToString()
{
StringBuilder sb1 = new StringBuilder(); sb1.AppendFormat("{0}\t\t{1}\t\t\t{2}\n",f,name,type); return sb1.ToString();
209
}
}
}
Экранная форма программы представлена на рис. 85.
Рис. 85. Экранная форма программы
Вопросы по теме:
1.Определение транслятора и компилятора. Их отличие
ипримеры.
2.Понятие компилятора и интерпретатора, отличия.
3.Общая схема работы транслятора, основные этапы.
4.Основные фазы компиляции на этапе анализа.
210