diff --git a/AboutDialog.Designer.cs b/AboutDialog.Designer.cs
new file mode 100644
index 0000000..3e31fdf
--- /dev/null
+++ b/AboutDialog.Designer.cs
@@ -0,0 +1,64 @@
+namespace TTGen
+{
+ partial class AboutDialog
+ {
+ ///
+ /// 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.AboutTxt = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // AboutTxt
+ //
+ this.AboutTxt.AutoSize = true;
+ this.AboutTxt.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.AboutTxt.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.AboutTxt.Location = new System.Drawing.Point(0, 0);
+ this.AboutTxt.Margin = new System.Windows.Forms.Padding(10);
+ this.AboutTxt.Name = "AboutTxt";
+ this.AboutTxt.Padding = new System.Windows.Forms.Padding(15);
+ this.AboutTxt.Size = new System.Drawing.Size(232, 46);
+ this.AboutTxt.TabIndex = 0;
+ this.AboutTxt.Text = "About text (set programmicatally)";
+ //
+ // AboutDialog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(284, 153);
+ this.Controls.Add(this.AboutTxt);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+ this.Name = "AboutDialog";
+ this.Text = "About";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label AboutTxt;
+ }
+}
\ No newline at end of file
diff --git a/AboutDialog.cs b/AboutDialog.cs
new file mode 100644
index 0000000..7968c1a
--- /dev/null
+++ b/AboutDialog.cs
@@ -0,0 +1,28 @@
+using System;
+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 TTGen
+{
+ public partial class AboutDialog : Form
+ {
+ public AboutDialog()
+ {
+ InitializeComponent();
+
+ AboutTxt.Text =
+ "Truth Table Generator v1.0 \n" +
+ "By Lee Zhen Yong AKA bruceoutdoors \n\n" +
+ "Built date: 30 Nov 2014 \n\n" +
+ "Uses Dijkstra's Shunting Yard algorithm \n" +
+ "and reverse polish notation. \n\n"
+ ;
+ }
+ }
+}
diff --git a/AboutDialog.resx b/AboutDialog.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/AboutDialog.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/App.config b/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BoolExpr.cs b/BoolExpr.cs
new file mode 100644
index 0000000..bd328bb
--- /dev/null
+++ b/BoolExpr.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TTGen
+{
+ class BoolExpr
+ {
+ private List Expression;
+ private const string mismatchParenErrorMsg =
+ "Error! Mismatched parenthesis in your expression!";
+
+ public BoolExpr(string input)
+ {
+ Expression = Token.Tokenize(input);
+ InsertANDs();
+
+ // convert to Reverse Polish Notation
+ Expression = ShuntingYard(Expression);
+ }
+
+ public bool Solve()
+ {
+ Stack stack = new Stack();
+
+ foreach (Token t in Expression) {
+ if (t.Category == Token.TokenCategory.Bool) {
+ stack.Push(t.BoolVal);
+ } else if (t.Category == Token.TokenCategory.Op) {
+ if (t.ArgCount > stack.Count) {
+ throw new Exception("The user has not input sufficient values in the expression!");
+ }
+
+ // evaluate the operator:
+ switch (t.Symbol) {
+ case '+':
+ stack.Push(stack.Pop() | stack.Pop());
+ break;
+ case '^':
+ stack.Push(stack.Pop() ^ stack.Pop());
+ break;
+ case '*':
+ stack.Push(stack.Pop() & stack.Pop());
+ break;
+ case '\'':
+ stack.Push(!stack.Pop());
+ break;
+ default:
+ throw new Exception("Error: Invalid operation!!");
+ }
+ }
+ }
+
+ if (stack.Count > 1) throw new Exception("Error: The user input has too many values.");
+
+ return stack.Pop();
+ }
+
+ // converts the token list to Reverse Polish Notation (RPN)
+ // using the Dijkstra's Shunting Yard algorithm
+ private List ShuntingYard(List list)
+ {
+ List outputQueue = new List();
+ Stack operatorStack = new Stack();
+
+ foreach (Token t in list) {
+ if (t.Category == Token.TokenCategory.Bool) {
+ outputQueue.Add(t);
+ } else if (t.Category == Token.TokenCategory.Op) {
+ while ((operatorStack.Count > 0) &&
+ (operatorStack.Peek().Category == Token.TokenCategory.Op) &&
+ (
+ (t.IsLeftAssoc && t.Precedence <= operatorStack.Peek().Precedence) ||
+ (!t.IsLeftAssoc && t.Precedence < operatorStack.Peek().Precedence)
+ )) {
+ outputQueue.Add(operatorStack.Pop());
+ }
+ operatorStack.Push(t);
+ } else if (t.Category == Token.TokenCategory.LeftParen) {
+ operatorStack.Push(t);
+ } else if (t.Category == Token.TokenCategory.RightParen) {
+ try {
+ while (operatorStack.Peek().Category != Token.TokenCategory.LeftParen) {
+ outputQueue.Add(operatorStack.Pop());
+ }
+ // pop left parenthesis from the stack
+ operatorStack.Pop();
+ } catch (InvalidOperationException) {
+ throw new Exception(mismatchParenErrorMsg);
+ }
+ }
+ }
+
+ // pop remaining operators in the stack to the output queue:
+ while (operatorStack.Count > 0) {
+ // If the operator token on the top of the stack is a parenthesis
+ if (operatorStack.Peek().Category == Token.TokenCategory.LeftParen ||
+ operatorStack.Peek().Category == Token.TokenCategory.RightParen) {
+ throw new Exception(mismatchParenErrorMsg);
+ }
+ outputQueue.Add(operatorStack.Pop());
+ }
+
+ return outputQueue;
+ }
+
+ private void InsertANDs()
+ {
+ // compare 2 tokens at a time:
+ int a = 0; int b = 1;
+ while (b < Expression.Count) {
+ // iterates through every possible location
+ // where * should be inserted
+ if ((Expression[a].Category == Token.TokenCategory.Bool &&
+ Expression[b].Category == Token.TokenCategory.LeftParen)
+ ||
+ (Expression[a].Category == Token.TokenCategory.Bool &&
+ Expression[b].Category == Token.TokenCategory.Bool)
+ ||
+ (Expression[a].Category == Token.TokenCategory.RightParen &&
+ Expression[b].Category == Token.TokenCategory.LeftParen)
+ ||
+ (Expression[a].Category == Token.TokenCategory.RightParen &&
+ Expression[b].Category == Token.TokenCategory.Bool)
+ || // conditions involving NOT (')
+ (Expression[a].Symbol == '\'' &&
+ Expression[b].Category == Token.TokenCategory.Bool)
+ ||
+ (Expression[a].Symbol == '\'' &&
+ Expression[b].Category == Token.TokenCategory.LeftParen)
+ ) {
+ Expression.Insert(b, new Token('*', Token.TokenCategory.Op, 4));
+ a++; b++;
+ }
+ a++; b++;
+ }
+ }
+
+ public List GetBoolVars()
+ {
+ List boolVars = new List();
+ foreach (var t in Expression) {
+ if (t.Category == Token.TokenCategory.Bool && t.isVariable) {
+ boolVars.Add(t.Symbol);
+ }
+ }
+ boolVars = boolVars.Distinct().ToList();
+ boolVars.Sort();
+
+ return boolVars;
+ }
+
+ // set variable value, returns true if successfully changed
+ public bool SetValue(char c, bool val)
+ {
+ bool success = false;
+ char ch = Char.ToUpper(c);
+ foreach (var t in Expression) {
+ if (t.Symbol == ch) {
+ t.BoolVal = val;
+ success = true;
+ }
+ }
+
+ return success;
+ }
+ }
+}
diff --git a/MainWindow.Designer.cs b/MainWindow.Designer.cs
new file mode 100644
index 0000000..6fd5e06
--- /dev/null
+++ b/MainWindow.Designer.cs
@@ -0,0 +1,253 @@
+namespace TTGen
+{
+ partial class MainWindow
+ {
+ ///
+ /// 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.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.howArToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.EqualityLbl = new System.Windows.Forms.Label();
+ this.mainLayout = new System.Windows.Forms.TableLayoutPanel();
+ this.TruthTableView = new System.Windows.Forms.ListView();
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.ErrorMsgLbl = new System.Windows.Forms.Label();
+ this.Input1 = new System.Windows.Forms.TextBox();
+ this.Input2 = new System.Windows.Forms.TextBox();
+ this.GenBtn = new System.Windows.Forms.Button();
+ this.menuStrip1.SuspendLayout();
+ this.mainLayout.SuspendLayout();
+ this.tableLayoutPanel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.howArToolStripMenuItem,
+ this.aboutToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(384, 24);
+ this.menuStrip1.TabIndex = 0;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // howArToolStripMenuItem
+ //
+ this.howArToolStripMenuItem.Name = "howArToolStripMenuItem";
+ this.howArToolStripMenuItem.Size = new System.Drawing.Size(64, 20);
+ this.howArToolStripMenuItem.Text = "How Ar?";
+ this.howArToolStripMenuItem.Click += new System.EventHandler(this.howArToolStripMenuItem_Click);
+ //
+ // aboutToolStripMenuItem
+ //
+ this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
+ this.aboutToolStripMenuItem.Size = new System.Drawing.Size(52, 20);
+ this.aboutToolStripMenuItem.Text = "About";
+ this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
+ //
+ // EqualityLbl
+ //
+ this.EqualityLbl.AutoSize = true;
+ this.EqualityLbl.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.EqualityLbl.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.EqualityLbl.ForeColor = System.Drawing.Color.Green;
+ this.EqualityLbl.Location = new System.Drawing.Point(3, 257);
+ this.EqualityLbl.Name = "EqualityLbl";
+ this.EqualityLbl.Padding = new System.Windows.Forms.Padding(0, 3, 0, 5);
+ this.EqualityLbl.Size = new System.Drawing.Size(378, 30);
+ this.EqualityLbl.TabIndex = 7;
+ this.EqualityLbl.Text = "Equality Label";
+ this.EqualityLbl.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ //
+ // mainLayout
+ //
+ this.mainLayout.ColumnCount = 1;
+ this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.mainLayout.Controls.Add(this.EqualityLbl, 0, 2);
+ this.mainLayout.Controls.Add(this.TruthTableView, 0, 1);
+ this.mainLayout.Controls.Add(this.tableLayoutPanel1, 0, 0);
+ this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mainLayout.Location = new System.Drawing.Point(0, 24);
+ this.mainLayout.Name = "mainLayout";
+ this.mainLayout.RowCount = 3;
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 80F));
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F));
+ this.mainLayout.Size = new System.Drawing.Size(384, 287);
+ this.mainLayout.TabIndex = 9;
+ //
+ // TruthTableView
+ //
+ this.TruthTableView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.TruthTableView.FullRowSelect = true;
+ this.TruthTableView.GridLines = true;
+ this.TruthTableView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this.TruthTableView.HoverSelection = true;
+ this.TruthTableView.Location = new System.Drawing.Point(10, 86);
+ this.TruthTableView.Margin = new System.Windows.Forms.Padding(10, 6, 10, 3);
+ this.TruthTableView.Name = "TruthTableView";
+ this.TruthTableView.Size = new System.Drawing.Size(364, 168);
+ this.TruthTableView.TabIndex = 9;
+ this.TruthTableView.UseCompatibleStateImageBehavior = false;
+ this.TruthTableView.View = System.Windows.Forms.View.Details;
+ //
+ // tableLayoutPanel1
+ //
+ this.tableLayoutPanel1.ColumnCount = 3;
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F));
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
+ this.tableLayoutPanel1.Controls.Add(this.label1, 0, 1);
+ this.tableLayoutPanel1.Controls.Add(this.label2, 0, 2);
+ this.tableLayoutPanel1.Controls.Add(this.ErrorMsgLbl, 0, 0);
+ this.tableLayoutPanel1.Controls.Add(this.Input1, 1, 1);
+ this.tableLayoutPanel1.Controls.Add(this.Input2, 1, 2);
+ this.tableLayoutPanel1.Controls.Add(this.GenBtn, 2, 1);
+ this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel1.Location = new System.Drawing.Point(6, 3);
+ this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(6, 3, 6, 3);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ this.tableLayoutPanel1.RowCount = 3;
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(372, 74);
+ this.tableLayoutPanel1.TabIndex = 10;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.label1.Location = new System.Drawing.Point(3, 20);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(24, 25);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "#1";
+ this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.label2.Location = new System.Drawing.Point(3, 45);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(24, 29);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "#2";
+ this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // ErrorMsgLbl
+ //
+ this.ErrorMsgLbl.AutoSize = true;
+ this.tableLayoutPanel1.SetColumnSpan(this.ErrorMsgLbl, 3);
+ this.ErrorMsgLbl.Dock = System.Windows.Forms.DockStyle.Left;
+ this.ErrorMsgLbl.ForeColor = System.Drawing.Color.Crimson;
+ this.ErrorMsgLbl.Location = new System.Drawing.Point(3, 0);
+ this.ErrorMsgLbl.Name = "ErrorMsgLbl";
+ this.ErrorMsgLbl.Size = new System.Drawing.Size(99, 20);
+ this.ErrorMsgLbl.TabIndex = 2;
+ this.ErrorMsgLbl.Text = "Error Message Text";
+ this.ErrorMsgLbl.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // Input1
+ //
+ this.Input1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.Input1.Location = new System.Drawing.Point(33, 23);
+ this.Input1.Name = "Input1";
+ this.Input1.Size = new System.Drawing.Size(251, 20);
+ this.Input1.TabIndex = 4;
+ this.Input1.TextChanged += new System.EventHandler(this.Input1_TextChanged);
+ //
+ // Input2
+ //
+ this.Input2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.Input2.Enabled = false;
+ this.Input2.Location = new System.Drawing.Point(33, 48);
+ this.Input2.Name = "Input2";
+ this.Input2.Size = new System.Drawing.Size(251, 20);
+ this.Input2.TabIndex = 5;
+ this.Input2.TextChanged += new System.EventHandler(this.Input2_TextChanged);
+ //
+ // GenBtn
+ //
+ this.GenBtn.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.GenBtn.Location = new System.Drawing.Point(290, 23);
+ this.GenBtn.Name = "GenBtn";
+ this.tableLayoutPanel1.SetRowSpan(this.GenBtn, 2);
+ this.GenBtn.Size = new System.Drawing.Size(79, 48);
+ this.GenBtn.TabIndex = 6;
+ this.GenBtn.Text = "Generate!";
+ this.GenBtn.UseVisualStyleBackColor = true;
+ this.GenBtn.Click += new System.EventHandler(this.GenBtn_Click);
+ //
+ // MainWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(384, 311);
+ this.Controls.Add(this.mainLayout);
+ this.Controls.Add(this.menuStrip1);
+ this.MainMenuStrip = this.menuStrip1;
+ this.MinimumSize = new System.Drawing.Size(400, 350);
+ this.Name = "MainWindow";
+ this.Text = "Truth Table Generator";
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.mainLayout.ResumeLayout(false);
+ this.mainLayout.PerformLayout();
+ this.tableLayoutPanel1.ResumeLayout(false);
+ this.tableLayoutPanel1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem howArToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
+ private System.Windows.Forms.Label EqualityLbl;
+ private System.Windows.Forms.TableLayoutPanel mainLayout;
+ private System.Windows.Forms.ListView TruthTableView;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label ErrorMsgLbl;
+ private System.Windows.Forms.TextBox Input1;
+ private System.Windows.Forms.TextBox Input2;
+ private System.Windows.Forms.Button GenBtn;
+
+
+
+
+
+ }
+}
+
diff --git a/MainWindow.cs b/MainWindow.cs
new file mode 100644
index 0000000..f5e5ea8
--- /dev/null
+++ b/MainWindow.cs
@@ -0,0 +1,209 @@
+using System;
+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 TTGen
+{
+ public partial class MainWindow : Form
+ {
+ private BoolExpr expression1;
+ private BoolExpr expression2;
+ private bool error1 = false;
+ private bool error2 = false;
+ private bool errors = false;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ ErrorMsgLbl.Text = "";
+ EqualityLbl.Text = "";
+ }
+
+ private void Input1_TextChanged(object sender, EventArgs e)
+ {
+ checkInputs();
+ }
+
+ private void Input2_TextChanged(object sender, EventArgs e)
+ {
+ checkInputs();
+ }
+
+ private void checkInputs()
+ {
+ if (Input1.Text != "") {
+ try {
+ expression1 = new BoolExpr(Input1.Text);
+ expression1.Solve();
+ error1 = false;
+ Input2.Enabled = true;
+ } catch (Exception ex) {
+ ErrorMsgLbl.Text = "Error in #1: " + ex.Message;
+ error1 = true;
+ Input2.Enabled = false;
+ }
+ } else {
+ error1 = false;
+ Input2.Enabled = false;
+ }
+
+ if (Input2.Enabled && Input2.Text != "") {
+ try {
+ expression2 = new BoolExpr(Input2.Text);
+ expression2.Solve();
+ error2 = false;
+ } catch (Exception ex) {
+ ErrorMsgLbl.Text = "Error in #2: " + ex.Message;
+ error2 = true;
+ }
+ } else {
+ error2 = false;
+ }
+
+ errors = (error1 || error2) ? true : false;
+ if (!errors) ErrorMsgLbl.Text = "";
+ }
+
+ private void GenBtn_Click(object sender, EventArgs e)
+ {
+ if (!validateInputs()) return;
+
+ // clear the previous table:
+ TruthTableView.Columns.Clear();
+ TruthTableView.Items.Clear();
+
+ List boolVars;
+
+ if (isInput2Enabled()) {
+ // combine both variables from 2 equations:
+ boolVars =
+ expression1.GetBoolVars()
+ .Concat(expression2.GetBoolVars())
+ .Distinct().ToList();
+ } else {
+ boolVars = expression1.GetBoolVars();
+ }
+
+ bool[,] inputTable = GenInputTable(boolVars.Count);
+
+ foreach (char c in boolVars) {
+ TruthTableView.Columns.Add(c.ToString());
+ }
+
+ // solve:
+ bool[] answer1 = new bool[inputTable.GetLength(0)];
+ bool[] answer2 = new bool[inputTable.GetLength(0)]; ;
+ for (int i = 0; i < inputTable.GetLength(0); i++) {
+ for (int j = 0; j < inputTable.GetLength(1); j++) {
+ expression1.SetValue(boolVars[j], inputTable[i, j]);
+ if (isInput2Enabled()) expression2.SetValue(boolVars[j], inputTable[i, j]);
+ }
+ answer1[i] = expression1.Solve();
+ if (isInput2Enabled()) answer2[i] = expression2.Solve();
+ }
+
+ bool equal = false;
+ if (isInput2Enabled()) equal = answer1.SequenceEqual(answer2);
+
+ TruthTableView.Columns.Add("#1");
+ if (isInput2Enabled() && !equal) TruthTableView.Columns.Add("#2");
+ for (int i = 0; i < inputTable.GetLength(0); i++) {
+ ListViewItem L = TruthTableView.Items.Add(getBoolStr(inputTable[i, 0]));
+ for (int j = 1; j < inputTable.GetLength(1); j++) {
+ L.SubItems.Add(getBoolStr(inputTable[i, j]));
+ }
+ L.SubItems.Add(getBoolStr(answer1[i]));
+ if (isInput2Enabled() && !equal) L.SubItems.Add(getBoolStr(answer2[i])); ;
+ }
+
+ if (isInput2Enabled()) {
+ if (equal) {
+ EqualityLbl.Text = "#1 and #2 are equivalent";
+ EqualityLbl.ForeColor = Color.Green;
+ } else {
+ EqualityLbl.Text = "#1 and #2 are NOT equivalent";
+ EqualityLbl.ForeColor = Color.Crimson;
+ }
+ } else {
+ EqualityLbl.Text = "";
+ }
+ }
+
+ private string getBoolStr(bool b)
+ {
+ return b ? "1" : "0";
+ }
+
+ private bool isInput2Enabled()
+ {
+ return Input2.Enabled && Input2.Text != "";
+ }
+
+ private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ AboutDialog box = new AboutDialog();
+ box.ShowDialog();
+ }
+
+ private bool validateInputs()
+ {
+ if (Input1.Text == "") {
+ MessageBox.Show("I can't generate a truth table without any input.");
+ return false;
+ }
+
+ if (errors) {
+ MessageBox.Show("Please make sure there are no errors with your input before generate the truth table.");
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool[,] GenInputTable(int col)
+ {
+ bool[,] table;
+ int row = (int)Math.Pow(2, col);
+
+ table = new bool[row, col];
+
+ int divider = row;
+
+ // iterate by column
+ for (int c = 0; c < col; c++) {
+ divider /= 2;
+ bool cell = false;
+ // iterate every row by this column's index:
+ for (int r = 0; r < row; r++) {
+ table[r, c] = cell;
+ if ((divider == 1) || ((r + 1) % divider == 0)) {
+ cell = !cell;
+ }
+ }
+ }
+
+ return table;
+ }
+
+ private void howArToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ string text =
+ "+ => OR gate\n" +
+ "* => AND gate\n" +
+ "^ => XOR gate\n" +
+ "' => NOT gate\n\n" +
+ "All letters are converted to upper case and\n" +
+ "interpreted as variables. All other inputs\n" +
+ "are invalid.\n\n" +
+ "Example: A(B^C')'+D\n\n" +
+ "#2 input allows you to compare 2 expressions.";
+ MessageBox.Show(text);
+ }
+ }
+}
diff --git a/MainWindow.resx b/MainWindow.resx
new file mode 100644
index 0000000..d5494e3
--- /dev/null
+++ b/MainWindow.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..be7e236
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TTGen
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainWindow());
+ }
+ }
+}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5e0df04
--- /dev/null
+++ b/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("BoolSolver")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BoolSolver")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[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("c84daeb3-5aa2-4f53-a7de-48e652b9566e")]
+
+// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..61c3bd1
--- /dev/null
+++ b/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.34014
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TTGen.Properties {
+ using System;
+
+
+ ///
+ /// 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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TTGen.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/Properties/Resources.resx b/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..3063c04
--- /dev/null
+++ b/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.34014
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TTGen.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.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/Properties/Settings.settings b/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/TTGenerator.csproj b/TTGenerator.csproj
new file mode 100644
index 0000000..07ec520
--- /dev/null
+++ b/TTGenerator.csproj
@@ -0,0 +1,100 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {2B519794-B44B-4B19-B19F-1DF123540C1D}
+ WinExe
+ Properties
+ TTGen
+ TTGen
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ AboutDialog.cs
+
+
+
+ Form
+
+
+ MainWindow.cs
+
+
+
+
+
+ AboutDialog.cs
+
+
+ MainWindow.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TTGenerator.sln b/TTGenerator.sln
new file mode 100644
index 0000000..8b726b1
--- /dev/null
+++ b/TTGenerator.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TTGenerator", "TTGenerator.csproj", "{2B519794-B44B-4B19-B19F-1DF123540C1D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2B519794-B44B-4B19-B19F-1DF123540C1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2B519794-B44B-4B19-B19F-1DF123540C1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2B519794-B44B-4B19-B19F-1DF123540C1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2B519794-B44B-4B19-B19F-1DF123540C1D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Token.cs b/Token.cs
new file mode 100644
index 0000000..e1bca4e
--- /dev/null
+++ b/Token.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace TTGen
+{
+ class Token
+ {
+ public enum TokenCategory
+ {
+ Undefined,
+ Bool,
+ Op,
+ LeftParen,
+ RightParen
+ };
+
+ // higher precendence gets executed first
+ public int Precedence { get; private set; }
+ public TokenCategory Category { get; private set; }
+ public char Symbol { get; private set; } // default value is 0
+ // if it not left associative, it is right.
+ public bool IsLeftAssoc { get; private set; }
+ public bool BoolVal { get; set; }
+ public bool isVariable { get; private set; }
+ public int ArgCount { get; private set; }
+
+ public Token(char symbol,
+ TokenCategory cat = TokenCategory.Undefined,
+ int precedence = -1,
+ int argCount = 0,
+ bool isLeftAssoc = true)
+ {
+ if (cat == TokenCategory.Bool) isVariable = true;
+ this.Category = cat;
+ this.Symbol = symbol;
+ this.Precedence = precedence;
+ this.IsLeftAssoc = isLeftAssoc;
+ this.ArgCount = argCount;
+ }
+
+ // constructor for values
+ public Token(char symbol, bool boolVal)
+ {
+ this.Category = TokenCategory.Bool;
+ this.BoolVal = boolVal;
+ this.Symbol = symbol;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("Category: {0}\nValue: {1}\nPrecedence: {2}\nAssociativity: {3}\n",
+ Category.ToString(),
+ Symbol == 0 ? BoolVal.ToString() : Symbol.ToString(),
+ Precedence,
+ IsLeftAssoc ? "left" : "right");
+ }
+
+ public static List Tokenize(string input)
+ {
+ List result = new List();
+ input = Regex.Replace(input, @"\s+", "");
+ foreach (char c in input) {
+ if (Char.IsLetter(c)) {
+ // assume all variables are uppercase
+ result.Add(new Token(Char.ToUpper(c), TokenCategory.Bool));
+ continue;
+ }
+ switch (c) {
+ case '0':
+ result.Add(new Token(c, false));
+ break;
+ case '1':
+ result.Add(new Token(c, true));
+ break;
+ case '(':
+ result.Add(new Token(c, TokenCategory.LeftParen));
+ break;
+ case ')':
+ result.Add(new Token(c, TokenCategory.RightParen));
+ break;
+ case '+':
+ result.Add(new Token(c, TokenCategory.Op, 2, 2));
+ break;
+ case '^':
+ result.Add(new Token(c, TokenCategory.Op, 3, 2));
+ break;
+ case '*':
+ result.Add(new Token(c, TokenCategory.Op, 4, 2));
+ break;
+ case '\'':
+ result.Add(new Token(c, TokenCategory.Op, 5, 1, false));
+ break;
+ default:
+ throw new Exception("Unable to tokenize. Make sure all characters are valid.");
+ }
+ }
+ return result;
+ }
+ }
+}