Мячина_6ЛР
.docxМИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ, СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ
Ордена Трудового Красного Знамени федеральное государственное бюджетное образовательное учреждение высшего образования
Московский технический университет связи и информатики
(МТУСИ)
Кафедра «Системное программирование»
Лабораторная работа №6
«Проектирование лексического анализатора»
по дисциплине «Построение простейшего дерева вывода»
Вариант 24
Выполнила:
студентка группы БФИ2203
Мячина Лада Андреевна
Проверила:
Старший преподаватель
Алексанян Диана Ашотовна
Москва, 2025 г.
Задание:
Выбрать вариант задания в соответствии с номером в журнале.
Построить множества крайних левых и крайних правых символов, множества крайних правых и крайних левых терминальных символов и матрицу операторного предшествования для заданной грамматики (если для построения синтаксического распознавателя предполагается использовать другой механизм, отличный от грамматик операторного предшествования, то форму его надо предварительно согласовать).
Заполнить матрицу предшествования для грамматики
Написать и отладить программу.
Подготовить и защитить отчет, продемонстрировать работу программы.
Вариант для выполнения работы представлен ниже:
Вариант |
№ грамматики |
Допустимые лексемы входного языка |
8, 24 |
4 |
Идентификаторы, римские числа |
Ход работы:
Исходная грамматика представлена на рисунке 1
Рисунок 1 – Исходная грамматика
Грамматика в форме Бэкуса-Наура представлена на рисунке 2.
Рисунок 2 – Грамматика в форме Бэкуса-Наура
Таблица 1 – крайне левые и крайне правые символы грамматики
Символ U |
L (U) |
R (U) |
S |
L(F) = {if, a} |
R(F) = {else, a, ;} |
F |
{if, a} |
{else, a, ;} |
T |
L(F) ∪ {;} = {if, a, ;} |
R(F) ∪ {;} = {else, a, ;} |
E |
{a} |
{a} |
Таблица 2 – крайне левые и крайне правые символы грамматики
Символ U |
L (U) |
R (U) |
S |
{if, a} |
{else, a, ;} |
F |
{if, a} |
{else, a, ;} |
T |
{if, a, ;} |
{else, a, ;} |
E |
{a} |
{a} |
Таблица 3 – Матрица операторного предшествования
|
if |
then |
else |
a |
:= |
< |
> |
= |
if |
|
= |
|
< |
|
|
|
|
then |
< |
|
= |
< |
|
|
|
|
else |
< |
|
> |
< |
|
|
|
|
a |
> |
> |
> |
|
= |
= |
= |
= |
:= |
|
|
|
= |
|
|
|
|
< |
|
|
|
= |
|
|
|
|
> |
|
|
|
= |
|
|
|
|
= |
|
|
|
= |
|
|
|
|
Листинг программы для выполнения ЛР:
import re
# Класс для представления лексемы
class Token:
def __init__(self, type, value):
self.type = type
self.value = value
def __str__(self):
return f"{self.type}('{self.value}')"
def __repr__(self):
return self.__str__()
# Лексический анализатор
class Lexer:
def __init__(self):
self.keywords = {'if', 'then', 'else'}
self.operators = {':=', '<', '>', '=', ';'}
def tokenize(self, text):
tokens = []
pos = 0
while pos < len(text):
# Пропускаем пробелы
if text[pos].isspace():
pos += 1
continue
# Проверяем ключевые слова и идентификаторы
if text[pos].isalpha():
# Извлекаем слово
word = ''
while pos < len(text) and (text[pos].isalpha() or text[pos] == '_' or text[pos].isdigit()):
word += text[pos]
pos += 1
if word in self.keywords:
tokens.append(Token(word.upper(), word))
else:
# Проверяем, является ли слово римским числом
if self.is_roman_numeral(word):
tokens.append(Token('A', word))
else:
tokens.append(Token('A', word)) # Идентификатор
# Проверяем операторы
elif text[pos] == ':' and pos + 1 < len(text) and text[pos + 1] == '=':
tokens.append(Token('ASSIGN', ':='))
pos += 2
elif text[pos] in self.operators:
tokens.append(Token(text[pos], text[pos]))
pos += 1
else:
raise ValueError(f"Неизвестный символ: {text[pos]}")
return tokens
def is_roman_numeral(self, s):
# Простая проверка на римские числа
roman_pattern = r'^[IVXLCDM]+$'
return bool(re.match(roman_pattern, s.upper()))
# Класс для представления узла дерева разбора
class ParseTreeNode:
def __init__(self, symbol, value=None):
self.symbol = symbol
self.value = value
self.children = []
def add_child(self, child):
self.children.append(child)
def __str__(self, level=0):
result = " " * level + f"{self.symbol}"
if self.value:
result += f"({self.value})"
result += "\n"
for child in self.children:
result += child.__str__(level + 1)
return result
# Улучшенный синтаксический анализатор
class ImprovedParser:
def __init__(self):
self.tokens = []
self.pos = 0
self.current_token = None
def parse(self, tokens):
self.tokens = tokens
self.pos = 0
self.current_token = self.tokens[0] if self.tokens else None
root = ParseTreeNode('S')
f_node = self.parse_F()
root.add_child(f_node)
return root
def advance(self):
self.pos += 1
if self.pos < len(self.tokens):
self.current_token = self.tokens[self.pos]
else:
self.current_token = None
def parse_F(self):
if self.current_token and self.current_token.type == 'IF':
return self.parse_if_statement()
else:
return self.parse_assignment()
def parse_if_statement(self):
# Обрабатываем 'if'
if_node = ParseTreeNode('F', 'if-then-else')
if_node.add_child(ParseTreeNode('IF', 'if'))
self.advance()
# Обрабатываем E (условие)
e_node = self.parse_E()
if_node.add_child(e_node)
# Обрабатываем 'then'
if self.current_token and self.current_token.type == 'THEN':
if_node.add_child(ParseTreeNode('THEN', 'then'))
self.advance()
else:
raise SyntaxError("Ожидается 'then'")
# Обрабатываем T или F после then
if self.current_token and self.current_token.type == ';':
t_node = self.parse_T()
if_node.add_child(t_node)
else:
f_node = self.parse_F()
if_node.add_child(f_node)
# Обрабатываем 'else' (если есть)
if self.current_token and self.current_token.type == 'ELSE':
if_node.add_child(ParseTreeNode('ELSE', 'else'))
self.advance()
# Обрабатываем F после else
f_node_else = self.parse_F()
if_node.add_child(f_node_else)
return if_node
def parse_T(self):
t_node = ParseTreeNode('T')
# Первый F (может отсутствовать)
if self.current_token and self.current_token.type == 'A':
f_node1 = self.parse_assignment()
t_node.add_child(f_node1)
# Первая ;
if self.current_token and self.current_token.type == ';':
t_node.add_child(ParseTreeNode(';', ';'))
self.advance()
else:
raise SyntaxError("Ожидается ';'")
# E
e_node = self.parse_E()
t_node.add_child(e_node)
# Вторая ;
if self.current_token and self.current_token.type == ';':
t_node.add_child(ParseTreeNode(';', ';'))
self.advance()
else:
raise SyntaxError("Ожидается ';'")
# Второй F (может отсутствовать)
if self.current_token and self.current_token.type == 'A':
f_node2 = self.parse_assignment()
t_node.add_child(f_node2)
return t_node
def parse_E(self):
e_node = ParseTreeNode('E')
# Первый A
if self.current_token and self.current_token.type == 'A':
e_node.add_child(ParseTreeNode('A', self.current_token.value))
self.advance()
else:
raise SyntaxError("Ожидается идентификатор или число")
# Оператор сравнения
if self.current_token and self.current_token.type in ['<', '>', '=']:
e_node.add_child(ParseTreeNode(self.current_token.type, self.current_token.value))
self.advance()
else:
raise SyntaxError("Ожидается оператор сравнения")
# Второй A
if self.current_token and self.current_token.type == 'A':
e_node.add_child(ParseTreeNode('A', self.current_token.value))
self.advance()
else:
raise SyntaxError("Ожидается идентификатор или число")
return e_node
def parse_assignment(self):
assign_node = ParseTreeNode('F', 'assignment')
# Левый A
if self.current_token and self.current_token.type == 'A':
assign_node.add_child(ParseTreeNode('A', self.current_token.value))
self.advance()
else:
raise SyntaxError("Ожидается идентификатор или число")
# ASSIGN
if self.current_token and self.current_token.type == 'ASSIGN':
assign_node.add_child(ParseTreeNode('ASSIGN', ':='))
self.advance()
else:
raise SyntaxError("Ожидается ':='")
# Правый A
if self.current_token and self.current_token.type == 'A':
assign_node.add_child(ParseTreeNode('A', self.current_token.value))
self.advance()
else:
raise SyntaxError("Ожидается идентификатор или число")
return assign_node
# Главная функция
def main():
print("Лабораторная работа №6: Построение простейшего дерева вывода")
print("Вариант 24: Идентификаторы, римские числа")
print("Грамматика:")
print("S → F")
print("F → if E then T else F | if E then F | a := a")
print("T → F ; E ; F | ; E ; F | F ; E ; | ; E ;")
print("E → a < a | a > a | a = a")
print()
# Пример входных данных
test_input = "if x := V then ; y > X ; else z := XX"
print(f"Входные данные: {test_input}")
print()
# Лексический анализ
lexer = Lexer()
try:
tokens = lexer.tokenize(test_input)
print("Результат лексического анализа:")
for token in tokens:
print(f" {token}")
print()
except Exception as e:
print(f"Ошибка лексического анализа: {e}")
return
# Синтаксический анализ
parser = ImprovedParser()
try:
parse_tree = parser.parse(tokens)
print("Дерево разбора:")
print(parse_tree)
print("Синтаксический анализ завершен успешно!")
except SyntaxError as e:
print(f"Ошибка синтаксического анализа: {e}")
except Exception as e:
print(f"Общая ошибка: {e}")
if __name__ == "__main__":
main()
Файл без ошибок:
Файл с ошибками
