I don't remember what changed here but I believe the core logic for parsing the math expression was updated to be 'better', perhaps more 'robust'. I don't think you can really call it that though considering it doesn't even make use of a syntax tree of any kind at the very least.

This commit is contained in:
2021-01-21 14:14:33 -06:00
parent c19ade9a40
commit 449b5b2f2d
7 changed files with 261 additions and 371 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+25 -17
View File
@@ -47,17 +47,19 @@
// //
// textBox1 // textBox1
// //
this.textBox1.Location = new System.Drawing.Point(921, 33); this.textBox1.Location = new System.Drawing.Point(613, 21);
this.textBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.textBox1.Name = "textBox1"; this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(447, 26); this.textBox1.Size = new System.Drawing.Size(299, 20);
this.textBox1.TabIndex = 0; this.textBox1.TabIndex = 0;
this.textBox1.Text = "2 * 5 / 2(1 + 2)"; this.textBox1.Text = "5000(2(2(1.08^10)-1)/0.08)";
// //
// button1 // button1
// //
this.button1.Location = new System.Drawing.Point(921, 758); this.button1.Location = new System.Drawing.Point(613, 492);
this.button1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.button1.Name = "button1"; this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(155, 92); this.button1.Size = new System.Drawing.Size(103, 60);
this.button1.TabIndex = 1; this.button1.TabIndex = 1;
this.button1.Text = "button1"; this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true; this.button1.UseVisualStyleBackColor = true;
@@ -77,13 +79,14 @@
this.mainLayout.Controls.Add(this.ActionsListView, 1, 3); this.mainLayout.Controls.Add(this.ActionsListView, 1, 3);
this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill; this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainLayout.Location = new System.Drawing.Point(0, 0); this.mainLayout.Location = new System.Drawing.Point(0, 0);
this.mainLayout.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.mainLayout.Name = "mainLayout"; this.mainLayout.Name = "mainLayout";
this.mainLayout.RowCount = 4; this.mainLayout.RowCount = 4;
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 19F));
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33F));
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 34F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 34F));
this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33F));
this.mainLayout.Size = new System.Drawing.Size(1371, 1113); this.mainLayout.Size = new System.Drawing.Size(914, 723);
this.mainLayout.TabIndex = 3; this.mainLayout.TabIndex = 3;
// //
// ExpressionBreakdownListView // ExpressionBreakdownListView
@@ -94,10 +97,11 @@
this.ExpressionBreakdownListView.Dock = System.Windows.Forms.DockStyle.Fill; this.ExpressionBreakdownListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.ExpressionBreakdownListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; this.ExpressionBreakdownListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.ExpressionBreakdownListView.HideSelection = false; this.ExpressionBreakdownListView.HideSelection = false;
this.ExpressionBreakdownListView.Location = new System.Drawing.Point(3, 33); this.ExpressionBreakdownListView.Location = new System.Drawing.Point(2, 21);
this.ExpressionBreakdownListView.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.ExpressionBreakdownListView.Name = "ExpressionBreakdownListView"; this.ExpressionBreakdownListView.Name = "ExpressionBreakdownListView";
this.mainLayout.SetRowSpan(this.ExpressionBreakdownListView, 2); this.mainLayout.SetRowSpan(this.ExpressionBreakdownListView, 2);
this.ExpressionBreakdownListView.Size = new System.Drawing.Size(446, 719); this.ExpressionBreakdownListView.Size = new System.Drawing.Size(297, 467);
this.ExpressionBreakdownListView.TabIndex = 3; this.ExpressionBreakdownListView.TabIndex = 3;
this.ExpressionBreakdownListView.UseCompatibleStateImageBehavior = false; this.ExpressionBreakdownListView.UseCompatibleStateImageBehavior = false;
this.ExpressionBreakdownListView.View = System.Windows.Forms.View.Details; this.ExpressionBreakdownListView.View = System.Windows.Forms.View.Details;
@@ -119,10 +123,11 @@
this.columnHeader4}); this.columnHeader4});
this.StepsListView.Dock = System.Windows.Forms.DockStyle.Fill; this.StepsListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.StepsListView.HideSelection = false; this.StepsListView.HideSelection = false;
this.StepsListView.Location = new System.Drawing.Point(455, 33); this.StepsListView.Location = new System.Drawing.Point(303, 21);
this.StepsListView.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.StepsListView.Name = "StepsListView"; this.StepsListView.Name = "StepsListView";
this.mainLayout.SetRowSpan(this.StepsListView, 2); this.mainLayout.SetRowSpan(this.StepsListView, 2);
this.StepsListView.Size = new System.Drawing.Size(460, 719); this.StepsListView.Size = new System.Drawing.Size(306, 467);
this.StepsListView.TabIndex = 4; this.StepsListView.TabIndex = 4;
this.StepsListView.UseCompatibleStateImageBehavior = false; this.StepsListView.UseCompatibleStateImageBehavior = false;
this.StepsListView.View = System.Windows.Forms.View.Details; this.StepsListView.View = System.Windows.Forms.View.Details;
@@ -144,9 +149,10 @@
this.columnHeader6}); this.columnHeader6});
this.SymbolsListView.Dock = System.Windows.Forms.DockStyle.Fill; this.SymbolsListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.SymbolsListView.HideSelection = false; this.SymbolsListView.HideSelection = false;
this.SymbolsListView.Location = new System.Drawing.Point(3, 758); this.SymbolsListView.Location = new System.Drawing.Point(2, 492);
this.SymbolsListView.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.SymbolsListView.Name = "SymbolsListView"; this.SymbolsListView.Name = "SymbolsListView";
this.SymbolsListView.Size = new System.Drawing.Size(446, 352); this.SymbolsListView.Size = new System.Drawing.Size(297, 229);
this.SymbolsListView.TabIndex = 5; this.SymbolsListView.TabIndex = 5;
this.SymbolsListView.UseCompatibleStateImageBehavior = false; this.SymbolsListView.UseCompatibleStateImageBehavior = false;
this.SymbolsListView.View = System.Windows.Forms.View.Details; this.SymbolsListView.View = System.Windows.Forms.View.Details;
@@ -167,9 +173,10 @@
this.columnHeader7}); this.columnHeader7});
this.ActionsListView.Dock = System.Windows.Forms.DockStyle.Fill; this.ActionsListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.ActionsListView.HideSelection = false; this.ActionsListView.HideSelection = false;
this.ActionsListView.Location = new System.Drawing.Point(455, 758); this.ActionsListView.Location = new System.Drawing.Point(303, 492);
this.ActionsListView.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.ActionsListView.Name = "ActionsListView"; this.ActionsListView.Name = "ActionsListView";
this.ActionsListView.Size = new System.Drawing.Size(460, 352); this.ActionsListView.Size = new System.Drawing.Size(306, 229);
this.ActionsListView.TabIndex = 6; this.ActionsListView.TabIndex = 6;
this.ActionsListView.UseCompatibleStateImageBehavior = false; this.ActionsListView.UseCompatibleStateImageBehavior = false;
this.ActionsListView.View = System.Windows.Forms.View.Details; this.ActionsListView.View = System.Windows.Forms.View.Details;
@@ -181,10 +188,11 @@
// //
// Form1 // Form1
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1371, 1113); this.ClientSize = new System.Drawing.Size(914, 723);
this.Controls.Add(this.mainLayout); this.Controls.Add(this.mainLayout);
this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.Name = "Form1"; this.Name = "Form1";
this.Text = "Form1"; this.Text = "Form1";
this.mainLayout.ResumeLayout(false); this.mainLayout.ResumeLayout(false);
+234 -352
View File
@@ -6,17 +6,14 @@ using System.Data;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Runtime.CompilerServices;
using System.Windows.Forms; using System.Windows.Forms;
namespace Engine namespace Engine
{ {
public partial class Form1 : Form public partial class Form1 : Form
{ {
//Invert over all expression (i + 7) ^ 2 -> -(i + 7) ^ 2 private Dictionary<string, double> Symbols { get; set; } = new Dictionary<string, double>();
private Stack<Node> Tree = new Stack<Node>();
private Dictionary<string, double> Symbols = new Dictionary<string, double>();
public Form1() public Form1()
{ {
@@ -31,37 +28,8 @@ namespace Engine
f.Reverse(); f.Reverse();
var stack = new Stack<Token>(f); var stack = new Stack<Token>(f);
ActionsListView.Items.Clear(); ActionsListView.Items.Clear();
PrintSymbolsTable();
button1.Text = "Result: " + NewCalc(stack); button1.Text = "Result: " + HandleAddAndSub(stack);
//var f2 = GetSubExpressions(f);
//PrintSteps(f2);
//PrintSymbolsTable();
//var result = Calc(f2);
//button1.Text = $"Result: {result}";
//var result = Calc(FlattenInput(s));
}
void PrintSteps(List<List<Node>> expressions)
{
StepsListView.Items.Clear();
for(var i = 0; i < expressions.Count; i++)
{
var expression = expressions[i];
var item = new ListViewItem($"Step {i + 1}");
var ex = string.Empty;
foreach (var token in expression)
{
if (!token.IsCoefficent)
ex += token.Value + " ";
else
ex += token.Value;
}
item.SubItems.Add(ex);
StepsListView.Items.Add(item);
}
} }
void PrintSymbolsTable() void PrintSymbolsTable()
@@ -84,274 +52,264 @@ namespace Engine
foreach(var token in tokens) foreach(var token in tokens)
{ {
var item = new ListViewItem(token.Value); var item = new ListViewItem(token.Value);
if(!token.IsCoefficent) item.SubItems.Add(token.Type.ToString()); item.SubItems.Add(token.Type.ToString());
else item.SubItems.Add(token.Type.ToString() + " (Coefficent)");
ExpressionBreakdownListView.Items.Add(item); ExpressionBreakdownListView.Items.Add(item);
} }
} }
double NewCalc(Stack<Token> tokens, double co = 1) double HandleParenthesis(Stack<Token> tokens, bool callerHasPriority = false)
{ {
var previousToken = new Token() { Type = TokenType.Unknown };
var runningValue = 0d; var runningValue = 0d;
var previousToken = new Token() { Type = TokenType.Unknown };
while(tokens.Count > 0) for(; ;)
{ {
var token = tokens.Pop(); if (tokens.Count == 0) break;
if (token.Type == TokenType.ExpEnd) var currentToken = tokens.Pop();
if(currentToken.Type == TokenType.Constant)
{
previousToken = currentToken;
continue;
}
else if(currentToken.Type == TokenType.ExpStart)
{
var tmp = HandleParenthesis(tokens);
runningValue = tmp;
}
else if(currentToken.Type == TokenType.Add || currentToken.Type == TokenType.Subtract)
{
var lookAHead = tokens.Pop();
if(lookAHead.Type == TokenType.ExpStart)
{
var tmp = HandleParenthesis(tokens);
if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), tmp, currentToken.Type);
else runningValue = Operate(runningValue, tmp, currentToken.Type);
continue;
}
tokens.Push(lookAHead);
tokens.Push(currentToken);
if (previousToken.Type != TokenType.Unknown) tokens.Push(previousToken);
else tokens.Push(new Token { Type = TokenType.Constant, Value = runningValue.ToString() });
runningValue = HandleAddAndSub(tokens);
previousToken.Type = TokenType.Unknown;
}
else if (currentToken.Type == TokenType.Power)
{
var lookAHead = tokens.Pop();
if(lookAHead.Type == TokenType.ExpStart)
{
var powerOf = HandleParenthesis(tokens, true);
runningValue = Operate(Convert.ToDouble(previousToken.Value), powerOf, currentToken.Type);
previousToken.Type = TokenType.Unknown;
continue;
}
var tmp = Operate(Convert.ToDouble(previousToken.Value), Convert.ToDouble(lookAHead.Value), currentToken.Type);
previousToken.Type = TokenType.Unknown;
runningValue = tmp;
}
else if (currentToken.Type == TokenType.Multiply || currentToken.Type == TokenType.Divide)
{
var lookAHead = tokens.Peek();
if (lookAHead.Type == TokenType.ExpStart)
{
tokens.Pop();
var tmpe = Operate(Convert.ToDouble(previousToken.Value), HandleParenthesis(tokens), currentToken.Type);
previousToken.Type = TokenType.Unknown;
runningValue = tmpe;
continue;
}
tokens.Push(currentToken);
if (previousToken.Type != TokenType.Unknown) tokens.Push(previousToken);
else tokens.Push(new Token { Type = TokenType.Constant, Value = runningValue.ToString() });
var tmp = HandleMultAndDiv(tokens);
previousToken.Type = TokenType.Unknown;
runningValue = tmp;
}
else if (currentToken.Type == TokenType.ExpEnd)
{ {
if(tokens.Count > 0 && tokens.Peek().Type == TokenType.Power) if(tokens.Count > 0 && tokens.Peek().Type == TokenType.Power)
{ {
var op = tokens.Pop(); //Pop the power of token before returning.
var powerOf = tokens.Pop(); tokens.Pop();
runningValue = Operate(runningValue, Convert.ToDouble(tokens.Pop().Value), TokenType.Power);
}
if(powerOf.Type == TokenType.Constant) if(!callerHasPriority && tokens.Count > 0 && (tokens.Peek().Type == TokenType.Multiply || tokens.Peek().Type == TokenType.Divide))
{
var op = tokens.Pop();
var twoAHead = tokens.Pop();
if(twoAHead.Type == TokenType.ExpStart)
{ {
ActionsListView.Items.Add($"Taking {runningValue} to the power of {powerOf.Value}."); runningValue = Operate(runningValue, HandleParenthesis(tokens, true), op.Type);
runningValue = Operate(runningValue, Convert.ToDouble(powerOf.Value), op.Type); }
else
{
runningValue = Operate(runningValue, Convert.ToDouble(twoAHead.Value), op.Type);
} }
} }
break; break;
} }
if(token.Type == TokenType.ExpStart)
{
runningValue = NewCalc(tokens);
continue;
}
if(token.IsCoefficent)
{
var lookAHead = tokens.Pop();
if (lookAHead.Type == TokenType.Variable)
{
ActionsListView.Items.Add($"{token.Value} is a coeffiecent, multiplying it against {Symbols[lookAHead.Value]} (Symbol '{lookAHead.Value}').");
runningValue += Convert.ToDouble(token.Value) * Symbols[lookAHead.Value];
if (previousToken.Type != TokenType.Unknown) throw new Exception("Token shouldn't have a valid value!");
//2a(
if(tokens.Count != 0 && tokens.Peek().Type == TokenType.ExpStart)
{
runningValue += NewCalc(tokens, runningValue);
}
previousToken = new Token() { Type = TokenType.Constant, Value = runningValue.ToString(), IsCoefficent = false };
continue;
}
else if (lookAHead.Type == TokenType.ExpStart)
{
runningValue += NewCalc(tokens, Convert.ToDouble(token.Value));
previousToken = new Token() { Type = TokenType.Constant, Value = runningValue.ToString(), IsCoefficent = false };
continue;
}
else throw new Exception("Invalid grammar!");
}
//If token is an operator
if(GetOperator(token.Value[0]) != TokenType.Unknown)
{
//Operator found
var lookAHead = tokens.Pop();
if(lookAHead.Type == TokenType.Constant && !lookAHead.IsCoefficent)
{
var tmpValue = 0d;
while (tokens.Count > 0 && (tokens.Peek().Type == TokenType.Multiply || tokens.Peek().Type == TokenType.Divide || tokens.Peek().Type == TokenType.Power))
{
var op = tokens.Pop();
if (op.Type != TokenType.Power)
{
var next = tokens.Pop();
if (next.Type == TokenType.ExpStart)
{
var returnValue = NewCalc(tokens);
if (tmpValue != 0)
{
ActionsListView.Items.Add($"{GetOperatorVerb(op.Type)} {tmpValue} (tmp) and {returnValue} (returnValue).");
tmpValue = Operate(tmpValue, returnValue, op.Type);
lookAHead.Value = tmpValue.ToString();
}
else
{
ActionsListView.Items.Add($"{GetOperatorVerb(op.Type)} {Convert.ToDouble(lookAHead.Value) * co} (lookAHead) and {returnValue} (returnValue).");
tmpValue = Operate(Convert.ToDouble(lookAHead.Value) * co, returnValue, op.Type);
lookAHead.Value = tmpValue.ToString();
}
continue;
}
if (tmpValue != 0)
{
ActionsListView.Items.Add($"{GetOperatorVerb(op.Type)} {tmpValue} (tmp) and {Convert.ToDouble(next.Value) * co} (next).");
tmpValue = Operate(tmpValue, Convert.ToDouble(next.Value) * co, op.Type);
lookAHead.Value = tmpValue.ToString();
}
else
{
ActionsListView.Items.Add($"{GetOperatorVerb(op.Type)} {Convert.ToDouble(lookAHead.Value) *co} (lookAHead) and {next.Value} (next).");
tmpValue = Operate(Convert.ToDouble(lookAHead.Value) *co, Convert.ToDouble(next.Value) *co, op.Type);
lookAHead.Value = tmpValue.ToString();
}
}
else if (op.Type == TokenType.Power)
{
}
}
//if(tokens.Count > 0 && (tokens.Peek().Type == TokenType.Divide || tokens.Peek().Type == TokenType.Multiply || tokens.Peek().Type == TokenType.Power))
//{
// var op = tokens.Pop();
// var con = tokens.Pop();
// //TODO: check if "con" is a variable, right now we're assuming its a constant.
// ActionsListView.Items.Add($"{GetOperatorVerb(op.Type)} {Convert.ToDouble(lookAHead.Value) * co} and {Convert.ToDouble(con.Value) * co} (Oder of Operations).");
// var tmp = Operate(Convert.ToDouble(lookAHead.Value) * co, Convert.ToDouble(con.Value) * co, op.Type);
// ActionsListView.Items.Add($"{GetOperatorVerb(token.Type)} {Convert.ToDouble(previousToken.Value) * co} and {tmp}.");
// runningValue += Operate(Convert.ToDouble(previousToken.Value) * co, tmp, token.Type);
// previousToken = new Token { Type = TokenType.Unknown };
//}
//else
//{
if (previousToken.Type != TokenType.Unknown)
{
ActionsListView.Items.Add($"{GetOperatorVerb(token.Type)} {Convert.ToDouble(previousToken.Value) * co} and {Convert.ToDouble(lookAHead.Value) * co}.");
runningValue += Operate(Convert.ToDouble(previousToken.Value) * co, Convert.ToDouble(lookAHead.Value) * co, token.Type);
}
else
{
ActionsListView.Items.Add($"{GetOperatorVerb(token.Type)} {runningValue} and {Convert.ToDouble(lookAHead.Value) * co}.");
runningValue = Operate(runningValue, Convert.ToDouble(lookAHead.Value) * co, token.Type);
}
//}
}
}
else if(token.Type == TokenType.Constant)
{
previousToken = token;
}
} }
return runningValue; return runningValue;
} }
List<List<Node>> GetSubExpressions(List<Node> tokens) double HandleMultAndDiv(Stack<Token> tokens)
{ {
var expressions = new List<List<Node>>(); var runningValue = 0d;
var stack = new Stack<List<Node>>(); var previousToken = new Token() { Type = TokenType.Unknown };
var tmp = new List<Node>();
var skipCount = 0;
var nestingLevel = 0;
for(var i = 0; i < tokens.Count; i++) for(; ;)
{ {
if(skipCount > 0) if (tokens.Count == 0) break;
//"Current" token.
if (tokens.Peek().Type != TokenType.Multiply && tokens.Peek().Type != TokenType.Divide && tokens.Peek().Type != TokenType.Constant && tokens.Peek().Type != TokenType.Variable)
{ {
skipCount--; break;
}
var currentToken = tokens.Pop();
if (currentToken.Type == TokenType.Constant)
{
previousToken = currentToken;
continue;
}
else if (currentToken.Type == TokenType.Multiply || currentToken.Type == TokenType.Divide)
{
var lookAHead = tokens.Pop();
if (lookAHead.Type == TokenType.ExpStart)
{
var tmp = HandleParenthesis(tokens, true);
if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), tmp, currentToken.Type);
else runningValue = Operate(runningValue, tmp, currentToken.Type);
previousToken.Type = TokenType.Unknown;
continue;
}
if (lookAHead.Type == TokenType.Constant)
{
if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), Convert.ToDouble(lookAHead.Value), currentToken.Type);
else runningValue = Operate(runningValue, Convert.ToDouble(lookAHead.Value), currentToken.Type);
previousToken.Type = TokenType.Unknown;
}
else if(lookAHead.Type == TokenType.ExpStart)
{
var tmp = HandleParenthesis(tokens, true);
if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), tmp, currentToken.Type);
else runningValue = Operate(runningValue, tmp, currentToken.Type);
previousToken.Type = TokenType.Unknown;
}
}
}
return runningValue;
}
double HandleAddAndSub(Stack<Token> tokens)
{
var runningValue = 0d;
var previousToken = new Token() { Type = TokenType.Unknown };
for(; ;)
{
if (tokens.Count == 0) break;
var currentToken = tokens.Pop();
if(currentToken.Type == TokenType.Constant)
{
previousToken = currentToken;
continue; continue;
} }
var token = tokens[i]; if (currentToken.Type == TokenType.ExpEnd)
//if (stack.Count > 0 && nestingLevel == 0)
//{
// if (!stack.Peek()[0].IsCoefficent)
// {
// var offset = 0;
// while(stack.Count > 0)
// {
// expressions.Insert(0, stack.Pop());
// offset++;
// }
// }
//}
if (token.IsCoefficent)
{ {
//var lookAhead = tokens[i + 1]; tokens.Push(currentToken);
break;
//if(lookAhead.Type != Node.Token.ExpStart)
//{
if (tmp.Count > 0) expressions.Add(new List<Node>(tmp));
expressions.Add(new List<Node>() { token });
//}
//else
//{
// stack.Push(new List<Node>(tmp));
//}
tmp.Clear();
} }
else if (token.Type == Node.Token.ExpStart)
if(currentToken.Type == TokenType.ExpStart)
{ {
nestingLevel++; var tmp = HandleParenthesis(tokens);
//if (i - 1 >= 0) runningValue = tmp;
//{
// var lookBehind = tokens[i - 1];
// if (lookBehind.IsCoefficent)
// {
// tmp.Remove(tmp.Last());
// expressions.Add(new List<Node>(tmp));
// tmp.Clear();
// stack.Push(new List<Node> { lookBehind });
// //tmp.Add(token);
// continue;
// }
//}
if (tmp.Count > 0) expressions.Add(new List<Node>(tmp));
tmp.Clear();
tmp.Add(token);
} }
else if(token.Type == Node.Token.ExpEnd) else if(currentToken.Type == TokenType.Add || currentToken.Type == TokenType.Subtract)
{ {
nestingLevel--; var lookAHead = tokens.Pop();
if (i + 1 < tokens.Count) if (lookAHead.Type == TokenType.ExpStart)
{ {
var lookAHead = tokens[i + 1]; var tmp = HandleParenthesis(tokens);
if (lookAHead.Type == Node.Token.Power) if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), tmp, currentToken.Type);
{ else runningValue = Operate(runningValue, tmp, currentToken.Type);
var toPowerOf = tokens[i + 2];
tmp.Add(token); previousToken.Type = TokenType.Unknown;
tmp.Add(lookAHead);
tmp.Add(toPowerOf); continue;
expressions.Add(new List<Node>(tmp));
tmp.Clear();
skipCount = 2;
continue;
}
} }
tmp.Add(token); if (tokens.Count > 0 && (tokens.Peek().Type == TokenType.Multiply || tokens.Peek().Type == TokenType.Divide))
if (tmp.Count > 0) expressions.Add(new List<Node>(tmp)); {
tmp.Clear(); tokens.Push(lookAHead);
var tmp = HandleMultAndDiv(tokens);
if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), tmp, currentToken.Type);
else runningValue = Operate(runningValue, tmp, currentToken.Type);
previousToken.Type = TokenType.Unknown;
}
else
{
if (runningValue == 0) runningValue = Operate(Convert.ToDouble(previousToken.Value), Convert.ToDouble(lookAHead.Value), currentToken.Type);
else runningValue = Operate(runningValue, Convert.ToDouble(lookAHead.Value), currentToken.Type);
previousToken.Type = TokenType.Unknown;
}
} }
else else if (currentToken.Type == TokenType.Multiply || currentToken.Type == TokenType.Divide)
{ {
tmp.Add(token); tokens.Push(currentToken);
if (previousToken.Type != TokenType.Unknown) tokens.Push(previousToken);
else tokens.Push(new Token { Type = TokenType.Constant, Value = runningValue.ToString() });
var tmp = HandleMultAndDiv(tokens);
previousToken.Type = TokenType.Unknown;
//TODO: this is wrong I'm sure.
runningValue = tmp;
} }
} }
if(tmp.Count > 0) return runningValue;
{
expressions.Add(new List<Node>(tmp));
}
return expressions;
} }
List<Token> FlattenInput(string expression) List<Token> FlattenInput(string expression)
@@ -377,13 +335,13 @@ namespace Engine
if(lookBehind.Type == TokenType.ExpEnd) if(lookBehind.Type == TokenType.ExpEnd)
{ {
tokens.Add(new Token() { Value = "^", Type = TokenType.Power, IsCoefficent = false }); tokens.Add(new Token() { Value = "^", Type = TokenType.Power });
} }
} }
if((i + 1) == expression.Length) if((i + 1) == expression.Length)
{ {
tokens.Add(new Token() { Value = $"{tmp}{c}", Type = TokenType.Constant, IsCoefficent = false });//new Node($"{tmp}{c}", Node.Token.Constant)); tokens.Add(new Token() { Value = $"{tmp}{c}", Type = TokenType.Constant });//new Node($"{tmp}{c}", Node.Token.Constant));
} }
parsingNumber = true; parsingNumber = true;
@@ -395,10 +353,11 @@ namespace Engine
{ {
if (parsingNumber) if (parsingNumber)
{ {
tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant, IsCoefficent = true });//new Node(tmp, Node.Token.Constant) { IsCoefficent = true }); tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant });
tokens.Add(new Token() { Value = "*", Type = TokenType.Multiply });
} }
tokens.Add(new Token() { Value = "(", Type = TokenType.ExpStart, IsCoefficent = false });//new Node("(", Node.Token.ExpStart)); tokens.Add(new Token() { Value = "(", Type = TokenType.ExpStart });//new Node("(", Node.Token.ExpStart));
parsingNumber = false; parsingNumber = false;
tmp = string.Empty; tmp = string.Empty;
continue; continue;
@@ -407,10 +366,10 @@ namespace Engine
{ {
if (parsingNumber) if (parsingNumber)
{ {
tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant, IsCoefficent = false }); //new Node(tmp, Node.Token.Constant)); tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant }); //new Node(tmp, Node.Token.Constant));
} }
tokens.Add(new Token() { Value = ")", Type = TokenType.ExpEnd, IsCoefficent = false }); //new Node(c.ToString(), Node.Token.ExpEnd)); tokens.Add(new Token() { Value = ")", Type = TokenType.ExpEnd }); //new Node(c.ToString(), Node.Token.ExpEnd));
parsingNumber = false; parsingNumber = false;
tmp = string.Empty; tmp = string.Empty;
continue; continue;
@@ -419,10 +378,10 @@ namespace Engine
{ {
if(parsingNumber) if(parsingNumber)
{ {
tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant, IsCoefficent = false }); //new Node(tmp, Node.Token.Constant)); tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant }); //new Node(tmp, Node.Token.Constant));
} }
tokens.Add(new Token() { Value = c.ToString(), Type = op, IsCoefficent = false });//new Node(c.ToString(), op)); tokens.Add(new Token() { Value = c.ToString(), Type = op });//new Node(c.ToString(), op));
parsingNumber = false; parsingNumber = false;
tmp = string.Empty; tmp = string.Empty;
continue; continue;
@@ -444,7 +403,7 @@ namespace Engine
if (lookBehind.Type == TokenType.ExpEnd) if (lookBehind.Type == TokenType.ExpEnd)
{ {
tokens.Add(new Token() { Value = "^", Type = TokenType.Power, IsCoefficent = false });//new Node("^", Node.Token.Power)); tokens.Add(new Token() { Value = "^", Type = TokenType.Power });
} }
} }
@@ -454,7 +413,8 @@ namespace Engine
if(lookAHead == '(') if(lookAHead == '(')
{ {
tokens.Add(new Token() { Value = c.ToString(), Type = TokenType.Variable, IsCoefficent = true }); tokens.Add(new Token() { Value = c.ToString(), Type = TokenType.Variable });
tokens.Add(new Token() { Value = "*", Type = TokenType.Multiply });
tmp = string.Empty; tmp = string.Empty;
parsingNumber = false; parsingNumber = false;
continue; continue;
@@ -463,10 +423,11 @@ namespace Engine
if (parsingNumber) if (parsingNumber)
{ {
tokens.Add(new Token() {Value = tmp, Type = TokenType.Constant, IsCoefficent = true }); tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant });
tokens.Add(new Token() { Value = "*", Type = TokenType.Multiply });
} }
tokens.Add(new Token() { Value = c.ToString(), Type = TokenType.Variable, IsCoefficent = false }); tokens.Add(new Token() { Value = c.ToString(), Type = TokenType.Variable });
parsingNumber = false; parsingNumber = false;
tmp = string.Empty; tmp = string.Empty;
} }
@@ -475,102 +436,24 @@ namespace Engine
return tokens; return tokens;
} }
//double Calc(List<List<Node>> expressions, double co = 1) double Operate(double n1, double n2, TokenType operation, [CallerMemberName] string source = "")
//{
// //Assumption: an operator is never last in the list.
// //double runningTotal = 0;
// double lastValue = 0;
// var next = true;
// Node previousToken = new Node("zzzz", Node.Token.Unknown);
// for(var i = 0; i < expressions.Count;)
// {
// if (!next) break;
// var tokens = expressions[i];
// expressions.RemoveAt(i);
// for (var j = 0; j < tokens.Count; j++)
// {
// var token = tokens[j];
// if(token.IsCoefficent)
// {
// if(tokens.Count == 1)
// {
// return Calc(expressions, Convert.ToDouble(token.Value));
// }
// }
// else if(token.Type == Node.Token.Constant)
// {
// previousToken = token;
// }
// else if(token.Type == Node.Token.Variable)
// {
// //TODO: do symbol lookup to get value for this variale.
// previousToken = new Node("666", Node.Token.Variable);
// }
// else if(GetOperator(token.Value[0]) != Node.Token.Unknown)
// {
// if(tokens.Count > j + 1)
// {
// j++;
// var lookAHead = tokens[j];
// if(lookAHead.Type == Node.Token.Constant)
// {
// if (previousToken.Type != Node.Token.Unknown)
// {
// lastValue = Operate(Convert.ToDouble(previousToken.Value) * co, Convert.ToDouble(lookAHead.Value) * co, token.Type);
// previousToken = new Node("zzzz", Node.Token.Unknown);
// }
// else
// lastValue = Operate(lastValue * co, Convert.ToDouble(lookAHead.Value) * co, token.Type);
// }
// }
// else
// {
// lastValue = Operate(Convert.ToDouble(previousToken.Value), Calc(expressions), token.Type);
// }
// }
// else if(token.Type == Node.Token.ExpStart)
// {
// }
// else if(token.Type == Node.Token.ExpEnd)
// {
// if(tokens.Count > j + 1)
// {
// var lookAHead = tokens[j + 1];
// if(lookAHead.Type == Node.Token.Power)
// {
// lookAHead = tokens[j + 2];
// lastValue = Operate(lastValue, Convert.ToDouble(lookAHead.Value), Node.Token.Power);
// }
// }
// next = false;
// }
// }
// }
// return lastValue;
//}
double Operate(double n1, double n2, TokenType operation)
{ {
switch(operation) switch(operation)
{ {
case TokenType.Add: case TokenType.Add:
ActionsListView.Items.Add($"From {source} {GetOperatorVerb(operation)} {n1} and {n2} to get {n1 + n2}");
return n1 + n2; return n1 + n2;
case TokenType.Divide: case TokenType.Divide:
ActionsListView.Items.Add($"From {source} {GetOperatorVerb(operation)} {n1} and {n2} to get {n1 / n2}");
return n1 / n2; return n1 / n2;
case TokenType.Multiply: case TokenType.Multiply:
ActionsListView.Items.Add($"From {source} {GetOperatorVerb(operation)} {n1} and {n2} to get {n1 * n2}");
return n1 * n2; return n1 * n2;
case TokenType.Power: case TokenType.Power:
ActionsListView.Items.Add($"From {source} {GetOperatorVerb(operation)} {n1} to the power of {n2} to get {Math.Pow(n1, n2)}");
return Math.Pow(n1, n2); return Math.Pow(n1, n2);
case TokenType.Subtract: case TokenType.Subtract:
ActionsListView.Items.Add($"From {source} {GetOperatorVerb(operation)} {n1} and {n2} to get {n1 - n2}");
return n1 - n2; return n1 - n2;
default: default:
throw new Exception("Token must be an operator!"); throw new Exception("Token must be an operator!");
@@ -618,7 +501,6 @@ namespace Engine
struct Token struct Token
{ {
public string Value; public string Value;
public bool IsCoefficent;
public TokenType Type; public TokenType Type;
} }
+2 -2
View File
@@ -1,7 +1,7 @@
A very terrible first go at parsing and calculating mathamtical expressions. A very terrible first go at parsing and calculating mathamtical expressions.
This project evolved into the [calc_engine](https://gitea.copyrightcrusader.org/glm94/calc_engine) project. This project evolved into the [calc_engine](https://gitea.copyrightcrusader.org/glm94/calc_engine) project which started as a striaght
This code was eventually ported into Python to create the calc_engine. That later evolved into the [terrain_generator](https://gitea.copyrightcrusader.org/glm94/terrain_generator). C# to Python port, complete with the very horrible logic this repo shows off. The calc_engine later evolved into the [terrain_generator](https://gitea.copyrightcrusader.org/glm94/terrain_generator).
However, this project is offically abandoned and no longer active. Its only here as a archive of what I've done, and how much I learned since However, this project is offically abandoned and no longer active. Its only here as a archive of what I've done, and how much I learned since
writing this code. Which, to be frank, is very bad. writing this code. Which, to be frank, is very bad.