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

IfStatement();

break;

case TokenType.LBRACE:

Block();

break;

case TokenType.SEMICOLON:

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

break;

default:

_errors.Add(new SyntaxError($"Неожиданный токен: {token.Value}", token.Line, token.Column));

_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, "Ожидается 'print'");

PrintEnd();

Expect(TokenType.SEMICOLON, "Ожидается ';' после print");

}

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

private void PrintEnd()

{

while (true)

{

Token token = CurrentToken();

if (token.Type == TokenType.STRING)

{

_position++;

}

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

{

Expression();

}

else

{

break;

}

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

{

_position++;

}

else

{

break;

}

}

}

// Scan → 'scan' Identifier ';'

private void ScanStatement()

{

Expect(TokenType.SCAN, "Ожидается 'scan'");

Token idToken = CurrentToken();

if (idToken.Type != TokenType.IDENTIFIER)

{

_errors.Add(new SyntaxError("Ожидается идентификатор после scan", idToken.Line, idToken.Column));

return;

}

_position++;

Expect(TokenType.SEMICOLON, "Ожидается ';' после scan");

}

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

private void AssignStatement()

{

Token idToken = CurrentToken();

Expect(TokenType.IDENTIFIER, "Ожидается идентификатор");

Expect(TokenType.ASSIGN, "Ожидается '='");

Expression();

Expect(TokenType.SEMICOLON, "Ожидается ';' после присваивания");

}

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

private void ForStatement()

{

Expect(TokenType.FOR, "Ожидается 'for'");

Token idToken = CurrentToken();

Expect(TokenType.IDENTIFIER, "Ожидается идентификатор цикла");

Expect(TokenType.ASSIGN, "Ожидается '=' в цикле for");

Expression();

Expect(TokenType.TO, "Ожидается 'to'");

Expression();

Expect(TokenType.LBRACE, "Ожидается '{' после for");

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

int loopBodyStart = _position;

int braceCount = 0;

// Пропускаем тело цикла для проверки синтаксиса

while (_position < _tokens.Count &&

!(braceCount == 0 && _tokens[_position].Type == TokenType.RBRACE) &&

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

{

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

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

_position++;

}

Expect(TokenType.RBRACE, "Ожидается '}' в конце цикла for");

}

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

private void IfStatement()

{

Expect(TokenType.IF, "Ожидается 'if'");

Expect(TokenType.LPAREN, "Ожидается '(' после if");

BoolExpression();

Expect(TokenType.RPAREN, "Ожидается ')' после условия");

// Проверяем then-часть

Statement();

// Проверяем else-часть, если она есть

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

{

Expect(TokenType.ELSE, "Ожидается 'else'");

Statement();

}

}

// BoolExpression → Expression Relop Expression

private void BoolExpression()

{

Expression();

Token op = CurrentToken();

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

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

{

_errors.Add(new SyntaxError($"Ожидается оператор сравнения, но найдено {op.Value}", op.Line, op.Column));

return;

}

_position++;

Expression();

}

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

private void Expression()

{

Term();

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

{

Token op = CurrentToken();

_position++;

Term();

}

}

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

private void Term()

{

Factor();

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

{

Token op = CurrentToken();

_position++;

Factor();

}

}

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

private void Factor()

{

Token token = CurrentToken();

if (token.Type == TokenType.IDENTIFIER)

{

_position++;

}

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

{

_position++;

}

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

{

_position++;

Expression();

Expect(TokenType.RPAREN, "Ожидается ')'");

}

else

{

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

}

}

}

// Интерпретатор CBAS (только выполнение, без проверки ошибок)

// Выполняет программу

public class Interpreter

{

private List<Token> _tokens;

private int _position;

private Dictionary<string, int> _variables; // значения переменных

public Interpreter(List<Token> tokens)

{

_tokens = tokens;

_position = 0;

_variables = new Dictionary<string, int>();

}

public void Execute()

{

Program();

}

private Token CurrentToken()

{

return _position < _tokens.Count ? _tokens[_position] : _tokens.Last();

}

private Token NextToken()

{

return _position < _tokens.Count ? _tokens[_position++] : _tokens.Last();

}

private bool Match(TokenType type)

{

if (CurrentToken().Type == type)

{

_position++;

return true;

}

return false;

}

private void Expect(TokenType type)

{

if (!Match(type))

{

throw new Exception($"Ожидается {type}, но найдено {CurrentToken().Type}");

}

}

// Program → Statement*

private void Program()

{

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

{

Statement();

}

}

// Statement → Print | Scan | Assign | For | If | Block | ';'

private void Statement()

{

Token token = CurrentToken();

switch (token.Type)

{

case TokenType.PRINT:

PrintStatement();

break;

case TokenType.SCAN:

ScanStatement();

break;

case TokenType.IDENTIFIER:

AssignStatement();

break;

case TokenType.FOR:

ForStatement();

break;

case TokenType.IF:

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