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}");
}
}
}
}
