commit c19ade9a40f2c30503db7cda52e3f18b92a2aef8 Author: Garritt McCune Date: Thu Jan 21 14:08:39 2021 -0600 'Engine.old' as the folder name says. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b43c61b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Engine/bin +Engine/obj \ No newline at end of file diff --git a/.vs/Engine/v16/.suo b/.vs/Engine/v16/.suo new file mode 100644 index 0000000..fdb35fe Binary files /dev/null and b/.vs/Engine/v16/.suo differ diff --git a/.vs/Engine/v16/Server/sqlite3/storage.ide b/.vs/Engine/v16/Server/sqlite3/storage.ide new file mode 100644 index 0000000..c287b95 Binary files /dev/null and b/.vs/Engine/v16/Server/sqlite3/storage.ide differ diff --git a/.vs/Engine/v16/Server/sqlite3/storage.ide-shm b/.vs/Engine/v16/Server/sqlite3/storage.ide-shm new file mode 100644 index 0000000..2e7d8db Binary files /dev/null and b/.vs/Engine/v16/Server/sqlite3/storage.ide-shm differ diff --git a/.vs/Engine/v16/Server/sqlite3/storage.ide-wal b/.vs/Engine/v16/Server/sqlite3/storage.ide-wal new file mode 100644 index 0000000..e3647b9 Binary files /dev/null and b/.vs/Engine/v16/Server/sqlite3/storage.ide-wal differ diff --git a/Engine.sln b/Engine.sln new file mode 100644 index 0000000..a16db7e --- /dev/null +++ b/Engine.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29009.5 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine", "Engine\Engine.csproj", "{EE5E8AF5-D774-46E7-B6B2-30ED358E2F36}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EE5E8AF5-D774-46E7-B6B2-30ED358E2F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE5E8AF5-D774-46E7-B6B2-30ED358E2F36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE5E8AF5-D774-46E7-B6B2-30ED358E2F36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE5E8AF5-D774-46E7-B6B2-30ED358E2F36}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C2514104-A503-4789-8345-7725070A8D62} + EndGlobalSection +EndGlobal diff --git a/Engine/App.config b/Engine/App.config new file mode 100644 index 0000000..5754728 --- /dev/null +++ b/Engine/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Engine/Engine.csproj b/Engine/Engine.csproj new file mode 100644 index 0000000..406fec6 --- /dev/null +++ b/Engine/Engine.csproj @@ -0,0 +1,85 @@ + + + + + Debug + AnyCPU + {EE5E8AF5-D774-46E7-B6B2-30ED358E2F36} + WinExe + Engine + Engine + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/Engine/ExpressionList.cs b/Engine/ExpressionList.cs new file mode 100644 index 0000000..8b5c8e6 --- /dev/null +++ b/Engine/ExpressionList.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Engine +{ + public static class ExpressionList + { + public static List Expressions = new List(); + } +} diff --git a/Engine/Form1.Designer.cs b/Engine/Form1.Designer.cs new file mode 100644 index 0000000..ffb8b2c --- /dev/null +++ b/Engine/Form1.Designer.cs @@ -0,0 +1,214 @@ +namespace Engine +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.mainLayout = new System.Windows.Forms.TableLayoutPanel(); + this.ExpressionBreakdownListView = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.StepsListView = new System.Windows.Forms.ListView(); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SymbolsListView = new System.Windows.Forms.ListView(); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.ActionsListView = new System.Windows.Forms.ListView(); + this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.mainLayout.SuspendLayout(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(921, 33); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(447, 26); + this.textBox1.TabIndex = 0; + this.textBox1.Text = "2 * 5 / 2(1 + 2)"; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(921, 758); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(155, 92); + this.button1.TabIndex = 1; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.Button1_Click); + // + // mainLayout + // + this.mainLayout.ColumnCount = 3; + this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 34F)); + this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + this.mainLayout.Controls.Add(this.button1, 2, 3); + this.mainLayout.Controls.Add(this.textBox1, 2, 1); + this.mainLayout.Controls.Add(this.ExpressionBreakdownListView, 0, 1); + this.mainLayout.Controls.Add(this.StepsListView, 1, 1); + this.mainLayout.Controls.Add(this.SymbolsListView, 0, 3); + this.mainLayout.Controls.Add(this.ActionsListView, 1, 3); + this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill; + this.mainLayout.Location = new System.Drawing.Point(0, 0); + this.mainLayout.Name = "mainLayout"; + 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.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, 33F)); + this.mainLayout.Size = new System.Drawing.Size(1371, 1113); + this.mainLayout.TabIndex = 3; + // + // ExpressionBreakdownListView + // + this.ExpressionBreakdownListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.ExpressionBreakdownListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.ExpressionBreakdownListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.ExpressionBreakdownListView.HideSelection = false; + this.ExpressionBreakdownListView.Location = new System.Drawing.Point(3, 33); + this.ExpressionBreakdownListView.Name = "ExpressionBreakdownListView"; + this.mainLayout.SetRowSpan(this.ExpressionBreakdownListView, 2); + this.ExpressionBreakdownListView.Size = new System.Drawing.Size(446, 719); + this.ExpressionBreakdownListView.TabIndex = 3; + this.ExpressionBreakdownListView.UseCompatibleStateImageBehavior = false; + this.ExpressionBreakdownListView.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Value"; + this.columnHeader1.Width = 100; + // + // columnHeader2 + // + this.columnHeader2.Text = "Token Type"; + this.columnHeader2.Width = 150; + // + // StepsListView + // + this.StepsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader3, + this.columnHeader4}); + this.StepsListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.StepsListView.HideSelection = false; + this.StepsListView.Location = new System.Drawing.Point(455, 33); + this.StepsListView.Name = "StepsListView"; + this.mainLayout.SetRowSpan(this.StepsListView, 2); + this.StepsListView.Size = new System.Drawing.Size(460, 719); + this.StepsListView.TabIndex = 4; + this.StepsListView.UseCompatibleStateImageBehavior = false; + this.StepsListView.View = System.Windows.Forms.View.Details; + // + // columnHeader3 + // + this.columnHeader3.Text = "Step"; + this.columnHeader3.Width = 100; + // + // columnHeader4 + // + this.columnHeader4.Text = "Expression"; + this.columnHeader4.Width = 300; + // + // SymbolsListView + // + this.SymbolsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader5, + this.columnHeader6}); + this.SymbolsListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.SymbolsListView.HideSelection = false; + this.SymbolsListView.Location = new System.Drawing.Point(3, 758); + this.SymbolsListView.Name = "SymbolsListView"; + this.SymbolsListView.Size = new System.Drawing.Size(446, 352); + this.SymbolsListView.TabIndex = 5; + this.SymbolsListView.UseCompatibleStateImageBehavior = false; + this.SymbolsListView.View = System.Windows.Forms.View.Details; + // + // columnHeader5 + // + this.columnHeader5.Text = "Symbol"; + this.columnHeader5.Width = 150; + // + // columnHeader6 + // + this.columnHeader6.Text = "Ref Count"; + this.columnHeader6.Width = 150; + // + // ActionsListView + // + this.ActionsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader7}); + this.ActionsListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.ActionsListView.HideSelection = false; + this.ActionsListView.Location = new System.Drawing.Point(455, 758); + this.ActionsListView.Name = "ActionsListView"; + this.ActionsListView.Size = new System.Drawing.Size(460, 352); + this.ActionsListView.TabIndex = 6; + this.ActionsListView.UseCompatibleStateImageBehavior = false; + this.ActionsListView.View = System.Windows.Forms.View.Details; + // + // columnHeader7 + // + this.columnHeader7.Text = "Action"; + this.columnHeader7.Width = 250; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1371, 1113); + this.Controls.Add(this.mainLayout); + this.Name = "Form1"; + this.Text = "Form1"; + this.mainLayout.ResumeLayout(false); + this.mainLayout.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TableLayoutPanel mainLayout; + private System.Windows.Forms.ListView ExpressionBreakdownListView; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ListView StepsListView; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ListView SymbolsListView; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ListView ActionsListView; + private System.Windows.Forms.ColumnHeader columnHeader7; + } +} + diff --git a/Engine/Form1.cs b/Engine/Form1.cs new file mode 100644 index 0000000..89fac4c --- /dev/null +++ b/Engine/Form1.cs @@ -0,0 +1,642 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Engine +{ + public partial class Form1 : Form + { + //Invert over all expression (i + 7) ^ 2 -> -(i + 7) ^ 2 + + private Stack Tree = new Stack(); + private Dictionary Symbols = new Dictionary(); + + public Form1() + { + InitializeComponent(); + } + + private void Button1_Click(object sender, EventArgs e) + { + var s = textBox1.Text; + var f = FlattenInput(s); + PrintFlatList(f); + f.Reverse(); + var stack = new Stack(f); + ActionsListView.Items.Clear(); + + button1.Text = "Result: " + NewCalc(stack); + //var f2 = GetSubExpressions(f); + //PrintSteps(f2); + //PrintSymbolsTable(); + //var result = Calc(f2); + //button1.Text = $"Result: {result}"; + //var result = Calc(FlattenInput(s)); + } + + void PrintSteps(List> 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() + { + SymbolsListView.Items.Clear(); + + foreach(var k in Symbols) + { + var item = new ListViewItem(k.Key); + item.SubItems.Add(k.Value.ToString()); + + SymbolsListView.Items.Add(item); + } + } + + void PrintFlatList(List tokens) + { + ExpressionBreakdownListView.Items.Clear(); + + foreach(var token in tokens) + { + var item = new ListViewItem(token.Value); + if(!token.IsCoefficent) item.SubItems.Add(token.Type.ToString()); + else item.SubItems.Add(token.Type.ToString() + " (Coefficent)"); + + ExpressionBreakdownListView.Items.Add(item); + } + } + + double NewCalc(Stack tokens, double co = 1) + { + var previousToken = new Token() { Type = TokenType.Unknown }; + var runningValue = 0d; + + while(tokens.Count > 0) + { + var token = tokens.Pop(); + + if (token.Type == TokenType.ExpEnd) + { + if(tokens.Count > 0 && tokens.Peek().Type == TokenType.Power) + { + var op = tokens.Pop(); + var powerOf = tokens.Pop(); + + if(powerOf.Type == TokenType.Constant) + { + ActionsListView.Items.Add($"Taking {runningValue} to the power of {powerOf.Value}."); + runningValue = Operate(runningValue, Convert.ToDouble(powerOf.Value), op.Type); + } + } + + 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; + } + + List> GetSubExpressions(List tokens) + { + var expressions = new List>(); + var stack = new Stack>(); + var tmp = new List(); + var skipCount = 0; + var nestingLevel = 0; + + for(var i = 0; i < tokens.Count; i++) + { + if(skipCount > 0) + { + skipCount--; + continue; + } + + var token = tokens[i]; + + //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]; + + //if(lookAhead.Type != Node.Token.ExpStart) + //{ + if (tmp.Count > 0) expressions.Add(new List(tmp)); + expressions.Add(new List() { token }); + //} + //else + //{ + // stack.Push(new List(tmp)); + //} + + tmp.Clear(); + } + else if (token.Type == Node.Token.ExpStart) + { + nestingLevel++; + + //if (i - 1 >= 0) + //{ + // var lookBehind = tokens[i - 1]; + + // if (lookBehind.IsCoefficent) + // { + // tmp.Remove(tmp.Last()); + // expressions.Add(new List(tmp)); + // tmp.Clear(); + // stack.Push(new List { lookBehind }); + // //tmp.Add(token); + // continue; + // } + //} + + if (tmp.Count > 0) expressions.Add(new List(tmp)); + tmp.Clear(); + tmp.Add(token); + } + else if(token.Type == Node.Token.ExpEnd) + { + nestingLevel--; + + if (i + 1 < tokens.Count) + { + var lookAHead = tokens[i + 1]; + + if (lookAHead.Type == Node.Token.Power) + { + var toPowerOf = tokens[i + 2]; + + tmp.Add(token); + tmp.Add(lookAHead); + tmp.Add(toPowerOf); + expressions.Add(new List(tmp)); + tmp.Clear(); + skipCount = 2; + continue; + } + } + + tmp.Add(token); + if (tmp.Count > 0) expressions.Add(new List(tmp)); + tmp.Clear(); + } + else + { + tmp.Add(token); + } + } + + if(tmp.Count > 0) + { + expressions.Add(new List(tmp)); + } + + return expressions; + } + + List FlattenInput(string expression) + { + //if (expression.Count(x => x == '(') == 1 && expression.Count(x => x == ')') == 1) throw new Exception("Unbalanced params!"); + //if(expression.Count(x => x == '(') % 2 != 0 || expression.Count(x => x == ')') % 2 != 0) throw new Exception("Unbalanced params!"); + Symbols.Clear(); + + var tokens = new List(); + var tmp = string.Empty; + var parsingNumber = false; + + for(var i = 0; i < expression.Length; i++) + { + var c = expression[i]; + var op = GetOperator(c); + + if (c == '.' || int.TryParse(c.ToString(), out int _)) + { + if(tokens.Count > 1) + { + var lookBehind = tokens[tokens.Count - 1]; + + if(lookBehind.Type == TokenType.ExpEnd) + { + tokens.Add(new Token() { Value = "^", Type = TokenType.Power, IsCoefficent = false }); + } + } + + if((i + 1) == expression.Length) + { + tokens.Add(new Token() { Value = $"{tmp}{c}", Type = TokenType.Constant, IsCoefficent = false });//new Node($"{tmp}{c}", Node.Token.Constant)); + } + + parsingNumber = true; + tmp += c; + + continue; + } + else if(c == '(') + { + 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 = "(", Type = TokenType.ExpStart, IsCoefficent = false });//new Node("(", Node.Token.ExpStart)); + parsingNumber = false; + tmp = string.Empty; + continue; + } + else if(c == ')') + { + if (parsingNumber) + { + tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant, IsCoefficent = false }); //new Node(tmp, Node.Token.Constant)); + } + + tokens.Add(new Token() { Value = ")", Type = TokenType.ExpEnd, IsCoefficent = false }); //new Node(c.ToString(), Node.Token.ExpEnd)); + parsingNumber = false; + tmp = string.Empty; + continue; + } + else if(op != TokenType.Unknown) + { + if(parsingNumber) + { + tokens.Add(new Token() { Value = tmp, Type = TokenType.Constant, IsCoefficent = false }); //new Node(tmp, Node.Token.Constant)); + } + + tokens.Add(new Token() { Value = c.ToString(), Type = op, IsCoefficent = false });//new Node(c.ToString(), op)); + parsingNumber = false; + tmp = string.Empty; + continue; + } + else if(c != ' ') + { + if (!Symbols.ContainsKey(c.ToString())) + { + Symbols.Add(c.ToString(), 1); + } + else + { + Symbols[c.ToString()]++; + } + + if (tokens.Count > 1) + { + var lookBehind = tokens[tokens.Count - 1]; + + if (lookBehind.Type == TokenType.ExpEnd) + { + tokens.Add(new Token() { Value = "^", Type = TokenType.Power, IsCoefficent = false });//new Node("^", Node.Token.Power)); + } + } + + if ((i + 1) < expression.Length) + { + var lookAHead = expression[i + 1]; + + if(lookAHead == '(') + { + tokens.Add(new Token() { Value = c.ToString(), Type = TokenType.Variable, IsCoefficent = true }); + tmp = string.Empty; + parsingNumber = false; + continue; + } + } + + if (parsingNumber) + { + tokens.Add(new Token() {Value = tmp, Type = TokenType.Constant, IsCoefficent = true }); + } + + tokens.Add(new Token() { Value = c.ToString(), Type = TokenType.Variable, IsCoefficent = false }); + parsingNumber = false; + tmp = string.Empty; + } + } + + return tokens; + } + + //double Calc(List> expressions, double co = 1) + //{ + // //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) + { + case TokenType.Add: + return n1 + n2; + case TokenType.Divide: + return n1 / n2; + case TokenType.Multiply: + return n1 * n2; + case TokenType.Power: + return Math.Pow(n1, n2); + case TokenType.Subtract: + return n1 - n2; + default: + throw new Exception("Token must be an operator!"); + } + } + + TokenType GetOperator(char c) + { + switch (c) + { + case '+': + return TokenType.Add; + case '-': + return TokenType.Subtract; + case '*': + return TokenType.Multiply; + case '^': + return TokenType.Power; + case '/': + return TokenType.Divide; + default: + return TokenType.Unknown; + } + } + + string GetOperatorVerb(TokenType type) + { + switch (type) + { + case TokenType.Add: + return "Adding"; + case TokenType.Divide: + return "Dividing"; + case TokenType.Multiply: + return "Multiplying"; + case TokenType.Power: + return "Raising"; + case TokenType.Subtract: + return "Subtracting"; + default: + throw new Exception("Token must be an operator!"); + } + } + + struct Token + { + public string Value; + public bool IsCoefficent; + public TokenType Type; + } + + enum TokenType + { + Add, + Subtract, + Multiply, + Divide, + Power, + Variable, + Constant, + ExpStart, + ExpEnd, + SubScript, + SuperScript, + Unknown + } + } +} + diff --git a/Engine/Form1.resx b/Engine/Form1.resx new file mode 100644 index 0000000..29dcb1b --- /dev/null +++ b/Engine/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Engine/Node.cs b/Engine/Node.cs new file mode 100644 index 0000000..4711760 --- /dev/null +++ b/Engine/Node.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Engine +{ + public class Node + { + public string Value; + public bool IsCoefficent = false; + public Token Type; + + public Node(string value, Token type) + { + Value = value; + Type = type; + } + + public enum Token + { + Add, + Subtract, + Multiply, + Divide, + Power, + Variable, + Constant, + ExpStart, + ExpEnd, + SubScript, + SuperScript, + Unknown + } + } +} diff --git a/Engine/Program.cs b/Engine/Program.cs new file mode 100644 index 0000000..5261fe8 --- /dev/null +++ b/Engine/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Engine +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Engine/Properties/AssemblyInfo.cs b/Engine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8f6340f --- /dev/null +++ b/Engine/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Engine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Engine")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ee5e8af5-d774-46e7-b6b2-30ed358e2f36")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Engine/Properties/Resources.Designer.cs b/Engine/Properties/Resources.Designer.cs new file mode 100644 index 0000000..3e55a1b --- /dev/null +++ b/Engine/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Engine.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Engine.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Engine/Properties/Resources.resx b/Engine/Properties/Resources.resx new file mode 100644 index 0000000..ffecec8 --- /dev/null +++ b/Engine/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Engine/Properties/Settings.Designer.cs b/Engine/Properties/Settings.Designer.cs new file mode 100644 index 0000000..4889b27 --- /dev/null +++ b/Engine/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Engine.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Engine/Properties/Settings.settings b/Engine/Properties/Settings.settings new file mode 100644 index 0000000..abf36c5 --- /dev/null +++ b/Engine/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..a0652cd --- /dev/null +++ b/readme.md @@ -0,0 +1,7 @@ +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 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). + +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. \ No newline at end of file