Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб. 5 ТАЯК.docx
Скачиваний:
0
Добавлен:
25.01.2026
Размер:
109.8 Кб
Скачать

IfStatement();

break;

case TokenType.LBRACE:

Block();

break;

case TokenType.SEMICOLON:

_position++; // Пустой оператор

break;

}

}

// Block → '{' Statement* '}'

private void Block()

{

Expect(TokenType.LBRACE);

while (CurrentToken().Type != TokenType.RBRACE && CurrentToken().Type != TokenType.EOF)

{

Statement();

}

Expect(TokenType.RBRACE);

}

// Print → 'print' PrintEnd ';'

private void PrintStatement()

{

Expect(TokenType.PRINT);

PrintEnd();

Expect(TokenType.SEMICOLON);

}

// PrintEnd → (String | Expression) (',' (String | Expression))*

private void PrintEnd()

{

bool first = true;

while (true)

{

Token token = CurrentToken();

if (token.Type == TokenType.STRING)

{

_position++;

Console.Write(token.Value);

}

else if (token.Type == TokenType.IDENTIFIER || token.Type == TokenType.NUMBER || token.Type == TokenType.LPAREN)

{

int value = Expression();

Console.Write(value);

}

else

{

break;

}

if (CurrentToken().Type == TokenType.COMMA)

{

_position++;

Console.Write(" ");

}

else

{

break;

}

first = false;

}

Console.WriteLine();

}

// Scan → 'scan' Identifier ';'

private void ScanStatement()

{

Expect(TokenType.SCAN);

Token idToken = CurrentToken();

Expect(TokenType.IDENTIFIER);

Console.Write($"Введите значение для {idToken.Value}: ");

Console.Out.Flush();

string input = Console.ReadLine();

if (int.TryParse(input, out int value))

{

_variables[idToken.Value] = value;

}

else

{

_variables[idToken.Value] = 0;

}

Expect(TokenType.SEMICOLON);

}

// Assign → Identifier '=' Expression ';'

private void AssignStatement()

{

Token idToken = CurrentToken();

Expect(TokenType.IDENTIFIER);

Expect(TokenType.ASSIGN);

int value = Expression();

_variables[idToken.Value] = value;

Expect(TokenType.SEMICOLON);

}

// For → 'for' Identifier '=' Expression 'to' Expression '{' Statement* '}'

private void ForStatement()

{

Expect(TokenType.FOR);

Token idToken = CurrentToken();

Expect(TokenType.IDENTIFIER);

Expect(TokenType.ASSIGN);

int startValue = Expression();

Expect(TokenType.TO);

int endValue = Expression();

Expect(TokenType.LBRACE);

// Сохраняем позицию начала тела цикла

int loopBodyStart = _position;

// Инициализируем переменную цикла

_variables[idToken.Value] = startValue;

// Выполняем цикл

while (_variables[idToken.Value] <= endValue)

{

// Восстанавливаем позицию для выполнения тела цикла

_position = loopBodyStart;

// Выполняем тело цикла

while (CurrentToken().Type != TokenType.RBRACE && CurrentToken().Type != TokenType.EOF)

{

Statement();

}

// Увеличиваем переменную цикла

_variables[idToken.Value]++;

}

// Пропускаем закрывающую скобку

Expect(TokenType.RBRACE);

}

// If → 'if' '(' BoolExpression ')' Statement

private void IfStatement()

{

Expect(TokenType.IF);

Expect(TokenType.LPAREN);

bool condition = BoolExpression();

Expect(TokenType.RPAREN);

// Сохраняем текущую позицию

int savedPosition = _position;

// Обрабатываем then-часть

if (condition)

{

// Выполняем then-блок

Statement();

// Пропускаем else-часть, если она есть

if (CurrentToken().Type == TokenType.ELSE)

{

SkipElse();

}

}

else

{

// Пропускаем then-блок

SkipStatement();

// Обрабатываем else-часть, если она есть

if (CurrentToken().Type == TokenType.ELSE)

{

Expect(TokenType.ELSE);

Statement();

}

}

}

// Пропустить один оператор

private void SkipStatement()

{

Token token = CurrentToken();

switch (token.Type)

{

case TokenType.LBRACE:

// Пропускаем блок

int braceCount = 1;

_position++;

while (braceCount > 0 && _position < _tokens.Count)

{

if (_tokens[_position].Type == TokenType.LBRACE) braceCount++;

if (_tokens[_position].Type == TokenType.RBRACE) braceCount--;

_position++;

}

break;

default:

// Пропускаем простой оператор до точки с запятой

while (_position < _tokens.Count &&

_tokens[_position].Type != TokenType.SEMICOLON &&

_tokens[_position].Type != TokenType.EOF)

{

_position++;

}

if (_position < _tokens.Count && _tokens[_position].Type == TokenType.SEMICOLON)

{

_position++;

}

break;

}

}

// Пропустить else-часть

private void SkipElse()

{

Expect(TokenType.ELSE);

SkipStatement();

}

// BoolExpression → Expression Relop Expression

private bool BoolExpression()

{

int left = Expression();

Token op = CurrentToken();

if (op.Type != TokenType.LT && op.Type != TokenType.GT &&

op.Type != TokenType.EQ && op.Type != TokenType.NE)

{

throw new Exception($"Ожидается оператор сравнения, но найдено {op.Value}");

}

_position++;

int right = Expression();

return op.Type switch

{

TokenType.LT => left < right,

TokenType.GT => left > right,

TokenType.EQ => left == right,

TokenType.NE => left != right,

_ => false

};

}

// Expression → Term {('+' | '-') Term}

private int Expression()

{

int value = Term();

while (CurrentToken().Type == TokenType.PLUS || CurrentToken().Type == TokenType.MINUS)

{

Token op = CurrentToken();

_position++;

int nextTerm = Term();

if (op.Type == TokenType.PLUS)

value += nextTerm;

else

value -= nextTerm;

}

return value;

}

// Term → Factor {('*' | '/') Factor}

private int Term()

{

int value = Factor();

while (CurrentToken().Type == TokenType.MULTIPLY || CurrentToken().Type == TokenType.DIVIDE)

{

Token op = CurrentToken();

_position++;

int nextFactor = Factor();

if (op.Type == TokenType.MULTIPLY)

value *= nextFactor;

else

{

if (nextFactor == 0)

{

value = 0;

}

else

{

value /= nextFactor;

}

}

}

return value;

}

// Factor → Identifier | Number | '(' Expression ')'

private int Factor()

{

Token token = CurrentToken();

if (token.Type == TokenType.IDENTIFIER)

{

_position++;

if (_variables.ContainsKey(token.Value))

{

return _variables[token.Value];

}

else

{

_variables[token.Value] = 0;

return 0;

}

}

else if (token.Type == TokenType.NUMBER)

{

_position++;

return int.Parse(token.Value);

}

else if (token.Type == TokenType.LPAREN)

{

_position++;

int value = Expression();

Expect(TokenType.RPAREN);

return value;

}

else

{

throw new Exception($"Ожидается число, переменная или '(', но найдено {token.Value}");

}

}

}

class Program

{

static void Main(string[] args)

{

string testProgram = @"print ""Программа на языке CBAS"", ""Начало работы"";

scan x;

for i = 1 to 5 {

print ""Итерация:"", i;

if (i < 3) {

print ""i меньше 3"";

} else {

print ""i больше или равно 3"";

}

}

y = x * 2;

print ""Результат y ="", y;

";

Console.WriteLine("=== ИНТЕРПРЕТАТОР CBAS ===");

Console.WriteLine("\nИсходная программа:");

Console.WriteLine("----------------------");

Console.WriteLine(testProgram);

Console.WriteLine("----------------------");

try

{

// 1. Лексический анализ

var lexer = new Lexer(testProgram);

var tokens = lexer.Tokenize();

// Проверка лексических ошибок

bool hasLexicalErrors = tokens.Any(t => t.Type == TokenType.ERROR);

if (hasLexicalErrors)

{

Console.WriteLine("\nЛексические ошибки:");

foreach (var token in tokens.Where(t => t.Type == TokenType.ERROR))

{

Console.WriteLine($" {token}");

}

Console.WriteLine("\nПрограмма не может быть выполнена из-за лексических ошибок.");

return;

}

// 2. Синтаксический анализ

Console.WriteLine("\nПроверка синтаксиса...");

var analyzer = new SyntaxAnalyzer(tokens);

var (syntaxSuccess, syntaxErrors) = analyzer.Analyze();

if (!syntaxSuccess)

{

Console.WriteLine("\nСинтаксические ошибки:");

foreach (var error in syntaxErrors)

{

Console.WriteLine($" {error}");

}

Console.WriteLine("\nПрограмма не может быть выполнена из-за синтаксических ошибок.");

return;

}

// 3. Если нет ошибок - выполнение программы

Console.WriteLine("\nРезультат выполнения:");

Console.WriteLine("======================");

var interpreter = new Interpreter(tokens);

interpreter.Execute();

Console.WriteLine("\n======================");

Console.WriteLine("Программа выполнена успешно.");

}

catch (Exception ex)

{

Console.WriteLine($"\nКритическая ошибка: {ex.Message}");

}

}

}

}

Соседние файлы в предмете Теория алгоритмических языков и компиляторов