Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Учебное пособие 800564

.pdf
Скачиваний:
3
Добавлен:
01.05.2022
Размер:
5.57 Mб
Скачать

Действия с идентификатором на различных фазах трансляции представлены в табл. 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