Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Код програми. Class ExpressionParser:⇐ ПредыдущаяСтр 127 из 127
Class ExpressionParser: // синтаксичний аналізатор namespace ExpressionParser { public static class ExpessionParser { public class ExpressionExeption: Exception { private string message;
public ExpressionExeption(string message) { this.message = message; }
public string Message { get { return message; } } } public static void Check(string s) { string strpat = @" \(*[\+\-\/\*]? [\d|\(]+\)*"; Regex pat = new Regex(strpat); MatchCollection matches =pat.Matches(s); int expressionPosition = 0, openBrackets=0, closeBrackets=0; string lastMatch = " ", prevMatch; foreach (char c in s) { if (c == '(') openBrackets++; else if (c == ')') closeBrackets++; } if(openBrackets! = closeBrackets) throw new ExpressionExeption(" Wrong brackets! ");
foreach (Match match in matches) if (match.Success) { prevMatch = lastMatch; lastMatch = match.Value; expressionPosition += prevMatch.Length; string error = " Invalid part of expresion at " + (expressionPosition+1) + " position \n" + s.Insert(expressionPosition, " [> "); if(s.IndexOf(lastMatch, expressionPosition, lastMatch.Length) == -1) throw new ExpressionExeption(error); } } public static double Parse(string s) { s = '(' + s + ')';
var operands = new Stack< double> (); var operators = new Stack< char> (); int pos = 0; object token; object prevToken = null;
do { token = GetToken(s, ref pos); // Для унарного + - if (token is char & & prevToken is char & & (char) prevToken == '(' & & ((char) token == '+' || (char) token == '-')) operands.Push(0); // Добавляємо 0 (імітуємо бінарну операцію, щоб не порушувати логіку програми) if (token is double) // Якщо операнд operands.Push((double) token); // то добавляємо в стек else if (token is char) // Якщо операція { if ((char) token == ')') { // Дужка - виключення з правил, яке виштовує всі операції до відкриваючоїся дужки. while (operators.Count > 0 & & operators.Peek()! = '(') Pop(operands, operators); operators.Pop(); //Видаляємо саму дужку " (" } else { while (CanPop((char) token, operators)) // Якщо можна виштовхнути Pop(operands, operators); // то виштовхуємо operators.Push((char) token); // Кидаємо нову операцію в стек } } prevToken = token; } while (token! = null);
if (operands.Count > 1 || operators.Count > 0) throw new ExpressionExeption(" Expression parsing error! "); return operands.Pop(); } private static void Pop(Stack< double> operands, Stack< char> operators) { double b = operands.Pop(); double a = operands.Pop(); switch (operators.Pop()) { case '+': operands.Push(a + b); break; case '-': operands.Push(a - b); break; case '*': operands.Push(a*b); break; case '/': operands.Push(a/b); break; } } private static bool CanPop(char op1, Stack< char> opertors) { if (opertors.Count == 0) return false; int p1 = GetPriority(op1); int p2 = GetPriority(opertors.Peek()); return p1 > = 0 & & p2 > = 0 & & p1 > = p2; } private static int GetPriority(char op) { switch (op) { case '(': return -1; // Не виштовхує і себе не дозволяє виштовхнути case '*': case '/': return 1; case '+': case '-': return 2; default: throw new ExpressionExeption(" An invalid operation"); } } private static object GetToken(string s, ref int pos) { ReadWhiteSpace(s, ref pos); if (pos == s.Length) // кінець рядка return null; if (char.IsDigit(s[pos])) return Convert.ToDouble(GetNumberString(s, ref pos)); return GetOperator(s, ref pos); } private static char GetOperator(string s, ref int pos) { return s[pos++]; } private static string GetNumberString(string s, ref int pos) { string res = " "; while (pos < s.Length & & (char.IsDigit(s[pos]) || s[pos] == '.')) res += s[pos++]; return res; }
private static void ReadWhiteSpace(string s, ref int pos) {// пропускаємо непотрібні символи while (pos < s.Length & & char.IsWhiteSpace(s[pos])) pos++; } } } Console app: namespace Cs3Console { class Program { static void Main(string[] args) { StreamReader stream = File.OpenText(" exps.txt"); string str; int i = 0; while ((str = stream.ReadLine())! = null) { Console.WriteLine(" Line {0}: {1} parsing...", ++i, str); try { ExpessionParser.Check(str); // перевірка виразу Console.WriteLine(" Parsed. Result = " + ExpessionParser.Parse(str)); // розбір виразу } catch (ExpessionParser.ExpressionExeption ex) {
Console.WriteLine(ex.Message); } }
} } }
GUI app: public partial class Calculator: Window { public Calculator() { InitializeComponent(); }
private void Window_KeyDown(object sender, KeyEventArgs e) { if (e.Key.ToString() == " Return") parse(); } void parse() { OutputTextBox.Text = ExpessionParser.Parse(InputTextBox.Text).ToString(); } private void InputTextBox_Loaded(object sender, RoutedEventArgs e) { Keyboard.Focus((IInputElement)sender); }
private void ButtonClick(object sender, RoutedEventArgs e) { var buttonText = ((Button) sender).Content.ToString();
if (buttonText == " =") parse(); else if (buttonText == " < -") InputTextBox.Text = InputTextBox.Text.Remove(InputTextBox.Text.Length - 1); else if (buttonText == " C") { InputTextBox.Text = " "; OutputTextBox.Text = " "; } else InputTextBox.Text += buttonText; Keyboard.Focus(InputTextBox); InputTextBox.CaretIndex = InputTextBox.Text.Length; } }
Результат виконання Console app: Результат виконання GUI app:
|