Не понимаю формулировку задачи - C#
Формулировка задачи:
Задание.
Предыдущее задание с формулировкой суммы.
Что от меня хотят и как мне начать это реализовывать?
Написать программу, которая по заданной сумме (определение понятия содержится в формулировке предыдущей задачи) вычисляет и печатает либо значение этой суммы, либо сообщение «при вычислении суммы получен промежуточный результат, превосходящий по модулю миллион».
Построить синтаксический анализатор для понятия сумма:
сумма ::= целое{знак-операции целое}*
целое ::= цифра{цифра}*
знак-операции ::=
Например, 021 + 16 и 22- суммы, а +1 –не сумма.
по сути,в предыдущем задании нужно построить синтаксический анализатор для понятия сумма. Но все равно не понимаю,как мое сделать
Решение задачи: «Не понимаю формулировку задачи»
textual
Листинг программы
using System; using System.IO; namespace Algorithms { internal class Program { static void Main() { try { //выводим сумму, если она корректна Console.WriteLine(ComputeExpr(Console.In)); } catch (Exception ex) { //Тут выводим либо, Incorrect expression!, если накосячил с вводом //или вот ту длинную хрень по заданию, если промежуточная сумма ...бла-бла-бла Console.WriteLine(ex.Message); } Console.ReadKey(true); } //доступные лексемы(состояния) private enum TokenValue { Plus = '+', Minus = '-', Number = 0, END = 1 } //текущее значение private static int _currNum; //текущая лексема или состояние - это как захочется назвать private static TokenValue _currToken; //это наше ограничение на промежуточное значение суммы private const int UPPER_BOUND = 1000000; //вбросит исключение, если переполнилась текущая сумма //по абсолютному значению, тем самым вычисление будет остановлено private static void CheckValue(int num) { if (Math.Abs(num) > UPPER_BOUND) throw new Exception("при вычислении суммы получен промежуточный результат, превосходящий по модулю миллион"); } //само решение private static int ComputeExpr(TextReader expr) { //получаем, первое число int left = GetPrimary(expr); //текущее состояние должно быть либо Plus, либо Minus, либо END //т.к. мы уже распарсили число. //погнали считать пока не упремся в конец выражения while (true) switch (_currToken) { //если +, то пытаемся получить следующее число //и прибавить результат. case TokenValue.Plus: left += GetPrimary(expr); CheckValue(left); break; //аналогично, только с '-' case TokenValue.Minus: left -= GetPrimary(expr); CheckValue(left); break; default: //достигли конца, возвращаем результат return left; } } //возвращает следующее число static int GetPrimary(TextReader expr) { //читаем и устанавливаем состояние //устанавливаются поля _currNum и _currToken ReadToken(expr); switch(_currToken) { case TokenValue.Number: int d = _currNum; //вновь читаем следующую лексему //она обязана быть уже не числом ReadToken(expr); return d; default: //если текущее состояние не число, то косяк, т.е. неверное выражение //швыряем исключение throw new Exception("Incorrect expression!"); } } //читалка лексем static void ReadToken(TextReader expr) { int c; //скипаем пробелы while ((c = expr.Peek()) != -1 && c == ' ') expr.Read(); //ну тут код сам за себя говорит, что он делает switch (c) { case '+': case '-': _currToken = (TokenValue)expr.Read(); break; case -1: case '\n': case '\r': _currToken = TokenValue.END; return; default: //все что не конец потока и не операция считаем числом //и пытаемся его распарсить _currNum = GetNum(expr); _currToken = TokenValue.Number; break; } } //парсинг числа private static int GetNum(TextReader exp) { int c, num = 0; //скипаем ведущие пробелы while ((c = exp.Peek()) != -1 && c == ' ') exp.Read() ; //если уперлись в конец потока или не в цифру, то опять же это косяк //в введенном выражении if(c == -1 || !char.IsDigit((char)c)) throw new Exception("Incorrect expression!"); //какая-то кривожопая проверка на конец числа, ну что есть то есть:) while ((c = exp.Peek()) != -1 && c != '+' && c != '-' && c != ' ' && c != '\n' && c != '\r') { //если не цифра, то кривые руки у пользователя if(!char.IsDigit((char)c)) throw new Exception("Incorrect expression!"); num *= 10; //сдвигаем на разряд влево num += (c - '0'); //если непонятно, то смотрим в таблицу ASCII и еще раз пытаемся понять exp.Read(); } return num; } } }