496 lines
20 KiB
C#
496 lines
20 KiB
C#
using BaseCalculator;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace Calculator
|
|
{
|
|
internal class Analaizer
|
|
{
|
|
private static int erposition = 0;
|
|
|
|
public static string expression = "";
|
|
|
|
public static ArrayList opz = null;
|
|
|
|
public static bool CheckCurrency()
|
|
{
|
|
bool result = true;
|
|
int num = 0;
|
|
for (int i = 0; i < expression.Length; i++)
|
|
{
|
|
if (expression[i] == '(')
|
|
{
|
|
num++;
|
|
}
|
|
else if (expression[i] == ')')
|
|
{
|
|
num--;
|
|
}
|
|
|
|
if (num < 0)
|
|
{
|
|
result = false;
|
|
erposition = i;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (num != 0)
|
|
{
|
|
result = false;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static string Format()
|
|
{
|
|
string text = "";
|
|
string text2 = "";
|
|
if (expression.Length <= 65536)
|
|
{
|
|
for (int i = 0; i < expression.Length; i++)
|
|
{
|
|
switch (expression[i])
|
|
{
|
|
case '0':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '1':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '2':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '3':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '4':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '5':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '6':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '7':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '8':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '9':
|
|
text = ((!(text2 == "число") && !(text2 == "")) ? (text + " " + expression[i]) : (text + expression[i]));
|
|
text2 = "число";
|
|
break;
|
|
case '+':
|
|
if (text2 != "")
|
|
{
|
|
if (!(text2 != "оператор"))
|
|
{
|
|
MessageBox.Show("Два подряд оператора на " + i + " символе.");
|
|
return "&Error 04 at " + i;
|
|
}
|
|
|
|
text = text + " " + expression[i];
|
|
}
|
|
else
|
|
{
|
|
text += expression[i];
|
|
}
|
|
|
|
text2 = "оператор";
|
|
break;
|
|
case '-':
|
|
if (text2 != "")
|
|
{
|
|
if (!(text2 != "оператор"))
|
|
{
|
|
MessageBox.Show("Два подряд оператора на " + i + " символе.");
|
|
return "&Error 04 at " + i;
|
|
}
|
|
|
|
text = text + " " + expression[i];
|
|
}
|
|
else
|
|
{
|
|
text += expression[i];
|
|
}
|
|
|
|
text2 = "оператор";
|
|
break;
|
|
case '*':
|
|
if (text2 != "")
|
|
{
|
|
if (!(text2 != "оператор"))
|
|
{
|
|
MessageBox.Show("Два подряд оператора на " + i + " символе.");
|
|
return "&Error 04 at " + i;
|
|
}
|
|
|
|
text = text + " " + expression[i];
|
|
}
|
|
else
|
|
{
|
|
text += expression[i];
|
|
}
|
|
|
|
text2 = "оператор";
|
|
break;
|
|
case '/':
|
|
if (text2 != "")
|
|
{
|
|
if (!(text2 != "оператор"))
|
|
{
|
|
MessageBox.Show("Два подряд оператора на " + i + " символе.");
|
|
return "&Error 04 at " + i;
|
|
}
|
|
|
|
text = text + " " + expression[i];
|
|
}
|
|
else
|
|
{
|
|
text += expression[i];
|
|
}
|
|
|
|
text2 = "оператор";
|
|
break;
|
|
case '(':
|
|
text = ((!(text2 != "")) ? (text + expression[i]) : (text + " " + expression[i]));
|
|
text2 = "скобка";
|
|
break;
|
|
case ')':
|
|
text = ((!(text2 != "")) ? (text + expression[i]) : (text + " " + expression[i]));
|
|
text2 = "скобка";
|
|
break;
|
|
case 'm':
|
|
if (i + 1 < expression.Length && expression[i + 1] == 'o' && expression[i + 2] == 'd')
|
|
{
|
|
if (text2 != "")
|
|
{
|
|
if (!(text2 != "оператор"))
|
|
{
|
|
MessageBox.Show("Два подряд оператора на " + i + " символе.");
|
|
return "&Error 04 at " + i;
|
|
}
|
|
|
|
string text3 = text;
|
|
text = text3 + " " + expression[i] + expression[i + 1] + expression[i + 2];
|
|
}
|
|
else
|
|
{
|
|
text = text + expression[i] + expression[i + 1] + expression[i + 2];
|
|
}
|
|
|
|
text2 = "оператор";
|
|
i += 2;
|
|
}
|
|
else
|
|
{
|
|
text = ((!(text2 != "")) ? (text + expression[i]) : (text + " " + expression[i]));
|
|
text2 = "унарный оператор";
|
|
}
|
|
|
|
break;
|
|
case 'p':
|
|
text = ((!(text2 != "")) ? (text + expression[i]) : (text + " " + expression[i]));
|
|
text2 = "унарный оператор";
|
|
break;
|
|
default:
|
|
MessageBox.Show("Неизвестный оператор на " + i + " символе.");
|
|
return "&Error 02 at " + i;
|
|
case ' ':
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (text2 != "оператор" && text2 != "унарный оператор")
|
|
{
|
|
return text + " ";
|
|
}
|
|
|
|
MessageBox.Show("Незаконченное выражение. ");
|
|
return "&Error 05";
|
|
}
|
|
|
|
MessageBox.Show("Слишком длинное выражение. Максмальная длина - 65536 символов.");
|
|
return "&Error 07";
|
|
}
|
|
|
|
public static ArrayList CreateStack()
|
|
{
|
|
ArrayList arrayList = new ArrayList(30);
|
|
Stack stack = new Stack(15);
|
|
string text = expression;
|
|
while (text != "")
|
|
{
|
|
string text2 = text.Substring(0, text.IndexOf(" "));
|
|
text = text.Substring(text.IndexOf(" ") + 1);
|
|
switch (text2)
|
|
{
|
|
case "(":
|
|
stack.Push(text2);
|
|
break;
|
|
case "m":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case "p":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case "*":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "*" || stack.Peek().ToString() == "/" || stack.Peek().ToString() == "mod" || stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case "/":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "*" || stack.Peek().ToString() == "/" || stack.Peek().ToString() == "mod" || stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case "mod":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "*" || stack.Peek().ToString() == "/" || stack.Peek().ToString() == "mod" || stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case "+":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "*" || stack.Peek().ToString() == "/" || stack.Peek().ToString() == "mod" || stack.Peek().ToString() == "+" || stack.Peek().ToString() == "-" || stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case "-":
|
|
while (stack.Count != 0 && (stack.Peek().ToString() == "*" || stack.Peek().ToString() == "/" || stack.Peek().ToString() == "mod" || stack.Peek().ToString() == "+" || stack.Peek().ToString() == "-" || stack.Peek().ToString() == "m" || stack.Peek().ToString() == "p"))
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Push(text2);
|
|
break;
|
|
case ")":
|
|
while (stack.Peek().ToString() != "(")
|
|
{
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
continue;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
stack.Pop();
|
|
break;
|
|
default:
|
|
if (arrayList.Capacity > arrayList.Count)
|
|
{
|
|
arrayList.Add(text2);
|
|
break;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
while (stack.Count != 0)
|
|
{
|
|
arrayList.Add(stack.Pop());
|
|
}
|
|
|
|
return arrayList;
|
|
}
|
|
|
|
public static string RunEstimate()
|
|
{
|
|
bool flag = false;
|
|
while (!flag)
|
|
{
|
|
int i = 0;
|
|
bool flag2 = false;
|
|
for (; i < opz.Count; i++)
|
|
{
|
|
if (flag2)
|
|
{
|
|
break;
|
|
}
|
|
|
|
flag2 = true;
|
|
try
|
|
{
|
|
switch (opz[i].ToString())
|
|
{
|
|
case "+":
|
|
opz[i - 2] = CalcClass.Add(Convert.ToInt64(opz[i - 2]), Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i - 1);
|
|
opz.RemoveAt(i - 1);
|
|
break;
|
|
case "-":
|
|
opz[i - 2] = CalcClass.Sub(Convert.ToInt64(opz[i - 2]), Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i - 1);
|
|
opz.RemoveAt(i - 1);
|
|
break;
|
|
case "*":
|
|
opz[i - 2] = CalcClass.Mult(Convert.ToInt64(opz[i - 2]), Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i - 1);
|
|
opz.RemoveAt(i - 1);
|
|
break;
|
|
case "/":
|
|
opz[i - 2] = CalcClass.Div(Convert.ToInt64(opz[i - 2]), Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i - 1);
|
|
opz.RemoveAt(i - 1);
|
|
break;
|
|
case "mod":
|
|
opz[i - 2] = CalcClass.Mod(Convert.ToInt64(opz[i - 2]), Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i - 1);
|
|
opz.RemoveAt(i - 1);
|
|
break;
|
|
case "m":
|
|
opz[i - 1] = CalcClass.IABS(Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i);
|
|
break;
|
|
case "p":
|
|
opz[i - 1] = CalcClass.ABS(Convert.ToInt64(opz[i - 1]));
|
|
opz.RemoveAt(i);
|
|
break;
|
|
default:
|
|
flag2 = false;
|
|
break;
|
|
}
|
|
}
|
|
catch (DivideByZeroException)
|
|
{
|
|
MessageBox.Show("Ошибка деления на 0");
|
|
return "Error 09";
|
|
}
|
|
catch (OverflowException)
|
|
{
|
|
MessageBox.Show("Слишком малое или слишком большое значение числа для int\n Числа должны быть в пределах от -2147483648 до 2147483647");
|
|
return "Error 06";
|
|
}
|
|
}
|
|
|
|
if (!flag2 && i == opz.Count)
|
|
{
|
|
flag = true;
|
|
}
|
|
|
|
string lastError = CalcClass.lastError;
|
|
if (lastError != "")
|
|
{
|
|
return lastError;
|
|
}
|
|
}
|
|
|
|
if (opz.Count != 1)
|
|
{
|
|
MessageBox.Show("Неверная синтаксическая конструкция входного выражения!");
|
|
return "Error 03";
|
|
}
|
|
|
|
return opz[0].ToString();
|
|
}
|
|
|
|
public static string Estimate()
|
|
{
|
|
if (CheckCurrency())
|
|
{
|
|
string text = Format();
|
|
if (text[0] == '&')
|
|
{
|
|
return text.Substring(1);
|
|
}
|
|
|
|
expression = text;
|
|
opz = CreateStack();
|
|
if (opz != null)
|
|
{
|
|
return RunEstimate();
|
|
}
|
|
|
|
MessageBox.Show("Суммарное количество чисел и операторов превышает 30!");
|
|
return "Error 08";
|
|
}
|
|
|
|
MessageBox.Show("Неправильная скобочная структура, ошибка на " + erposition + " символе !");
|
|
return "Error 01 at " + erposition;
|
|
}
|
|
}
|
|
}
|