Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Код програми. Class ExpressionParser:






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:


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.018 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал