diff --git a/LexicalAnalyzer.csproj b/LexicalAnalyzer.csproj
index 8cbe81d..27346cc 100644
--- a/LexicalAnalyzer.csproj
+++ b/LexicalAnalyzer.csproj
@@ -46,7 +46,7 @@
-
+
Form
@@ -56,6 +56,8 @@
+
+
MainForm.cs
diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs
index 582cb87..2f7f14e 100644
--- a/MainForm.Designer.cs
+++ b/MainForm.Designer.cs
@@ -28,9 +28,9 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
- System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
+ System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
this.tabControl1 = new System.Windows.Forms.TabControl();
- this.tabPage_sourceFile = new System.Windows.Forms.TabPage();
+ this.tabPage_SourceFile = new System.Windows.Forms.TabPage();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.textBox_FileViewer = new System.Windows.Forms.TextBox();
this.button_openFile = new System.Windows.Forms.Button();
@@ -39,36 +39,53 @@ private void InitializeComponent()
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.dataGridView_table = new System.Windows.Forms.DataGridView();
this.Number = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.Type = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Value = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Type = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.tabPage_SyntaxTree = new System.Windows.Forms.TabPage();
+ this.groupBox3 = new System.Windows.Forms.GroupBox();
+ this.button_RegenerateTreeView = new System.Windows.Forms.Button();
+ this.button_ShowDeepestTreeView = new System.Windows.Forms.Button();
+ this.button_ToggleTreeViewVisib = new System.Windows.Forms.Button();
+ this.SyntaxTreeView = new System.Windows.Forms.TreeView();
+ this.tabPage_CodeGeneration = new System.Windows.Forms.TabPage();
+ this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.button_SimpleButton = new System.Windows.Forms.Button();
+ this.button_AnotherButton = new System.Windows.Forms.Button();
+ this.treeView1 = new System.Windows.Forms.TreeView();
this.tabControl1.SuspendLayout();
- this.tabPage_sourceFile.SuspendLayout();
+ this.tabPage_SourceFile.SuspendLayout();
this.groupBox1.SuspendLayout();
this.tabPage_LexicalTable.SuspendLayout();
this.groupBox2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView_table)).BeginInit();
+ this.tabPage_SyntaxTree.SuspendLayout();
+ this.groupBox3.SuspendLayout();
+ this.tabPage_CodeGeneration.SuspendLayout();
+ this.groupBox4.SuspendLayout();
this.SuspendLayout();
//
// tabControl1
//
- this.tabControl1.Controls.Add(this.tabPage_sourceFile);
+ this.tabControl1.Controls.Add(this.tabPage_SourceFile);
this.tabControl1.Controls.Add(this.tabPage_LexicalTable);
+ this.tabControl1.Controls.Add(this.tabPage_SyntaxTree);
+ this.tabControl1.Controls.Add(this.tabPage_CodeGeneration);
this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(785, 460);
this.tabControl1.TabIndex = 0;
//
- // tabPage_sourceFile
+ // tabPage_SourceFile
//
- this.tabPage_sourceFile.BackColor = System.Drawing.Color.Transparent;
- this.tabPage_sourceFile.Controls.Add(this.groupBox1);
- this.tabPage_sourceFile.Location = new System.Drawing.Point(4, 22);
- this.tabPage_sourceFile.Name = "tabPage_sourceFile";
- this.tabPage_sourceFile.Padding = new System.Windows.Forms.Padding(3);
- this.tabPage_sourceFile.Size = new System.Drawing.Size(777, 434);
- this.tabPage_sourceFile.TabIndex = 0;
- this.tabPage_sourceFile.Text = "Source file";
+ this.tabPage_SourceFile.BackColor = System.Drawing.Color.Transparent;
+ this.tabPage_SourceFile.Controls.Add(this.groupBox1);
+ this.tabPage_SourceFile.Location = new System.Drawing.Point(4, 22);
+ this.tabPage_SourceFile.Name = "tabPage_SourceFile";
+ this.tabPage_SourceFile.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage_SourceFile.Size = new System.Drawing.Size(777, 434);
+ this.tabPage_SourceFile.TabIndex = 0;
+ this.tabPage_SourceFile.Text = "Source file";
//
// groupBox1
//
@@ -139,19 +156,20 @@ private void InitializeComponent()
this.dataGridView_table.AllowUserToDeleteRows = false;
this.dataGridView_table.AllowUserToResizeColumns = false;
this.dataGridView_table.AllowUserToResizeRows = false;
+ this.dataGridView_table.BackgroundColor = System.Drawing.SystemColors.Control;
this.dataGridView_table.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dataGridView_table.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Number,
- this.Type,
- this.Value});
- dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
- dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Window;
- dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
- dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
- dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.ControlDark;
- dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
- dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
- this.dataGridView_table.DefaultCellStyle = dataGridViewCellStyle1;
+ this.Value,
+ this.Type});
+ dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+ dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window;
+ dataGridViewCellStyle2.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
+ dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText;
+ dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.ActiveCaption;
+ dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.ControlText;
+ dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
+ this.dataGridView_table.DefaultCellStyle = dataGridViewCellStyle2;
this.dataGridView_table.Location = new System.Drawing.Point(6, 19);
this.dataGridView_table.MultiSelect = false;
this.dataGridView_table.Name = "dataGridView_table";
@@ -171,6 +189,14 @@ private void InitializeComponent()
this.Number.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Number.Width = 200;
//
+ // Value
+ //
+ this.Value.HeaderText = "Value";
+ this.Value.Name = "Value";
+ this.Value.ReadOnly = true;
+ this.Value.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this.Value.Width = 300;
+ //
// Type
//
this.Type.HeaderText = "Type";
@@ -179,13 +205,118 @@ private void InitializeComponent()
this.Type.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Type.Width = 245;
//
- // Value
+ // tabPage_SyntaxTree
//
- this.Value.HeaderText = "Value";
- this.Value.Name = "Value";
- this.Value.ReadOnly = true;
- this.Value.Resizable = System.Windows.Forms.DataGridViewTriState.False;
- this.Value.Width = 300;
+ this.tabPage_SyntaxTree.Controls.Add(this.groupBox3);
+ this.tabPage_SyntaxTree.Location = new System.Drawing.Point(4, 22);
+ this.tabPage_SyntaxTree.Name = "tabPage_SyntaxTree";
+ this.tabPage_SyntaxTree.Size = new System.Drawing.Size(777, 434);
+ this.tabPage_SyntaxTree.TabIndex = 2;
+ this.tabPage_SyntaxTree.Text = "Syntax tree";
+ this.tabPage_SyntaxTree.UseVisualStyleBackColor = true;
+ //
+ // groupBox3
+ //
+ this.groupBox3.Controls.Add(this.button_RegenerateTreeView);
+ this.groupBox3.Controls.Add(this.button_ShowDeepestTreeView);
+ this.groupBox3.Controls.Add(this.button_ToggleTreeViewVisib);
+ this.groupBox3.Controls.Add(this.SyntaxTreeView);
+ this.groupBox3.Location = new System.Drawing.Point(8, 6);
+ this.groupBox3.Name = "groupBox3";
+ this.groupBox3.Size = new System.Drawing.Size(760, 421);
+ this.groupBox3.TabIndex = 1;
+ this.groupBox3.TabStop = false;
+ this.groupBox3.Text = "Syntax tree";
+ //
+ // button_RegenerateTreeView
+ //
+ this.button_RegenerateTreeView.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
+ this.button_RegenerateTreeView.Location = new System.Drawing.Point(343, 18);
+ this.button_RegenerateTreeView.Name = "button_RegenerateTreeView";
+ this.button_RegenerateTreeView.Size = new System.Drawing.Size(129, 22);
+ this.button_RegenerateTreeView.TabIndex = 4;
+ this.button_RegenerateTreeView.Text = "Regenerate tree";
+ this.button_RegenerateTreeView.UseVisualStyleBackColor = true;
+ this.button_RegenerateTreeView.Click += new System.EventHandler(this.button_RegenerateTreeView_Click);
+ //
+ // button_ShowDeepestTreeView
+ //
+ this.button_ShowDeepestTreeView.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
+ this.button_ShowDeepestTreeView.Location = new System.Drawing.Point(484, 18);
+ this.button_ShowDeepestTreeView.Name = "button_ShowDeepestTreeView";
+ this.button_ShowDeepestTreeView.Size = new System.Drawing.Size(129, 22);
+ this.button_ShowDeepestTreeView.TabIndex = 3;
+ this.button_ShowDeepestTreeView.Text = "Show deepest path";
+ this.button_ShowDeepestTreeView.UseVisualStyleBackColor = true;
+ this.button_ShowDeepestTreeView.Click += new System.EventHandler(this.button_ShowDeepestTreeView_Click);
+ //
+ // button_ToggleTreeViewVisib
+ //
+ this.button_ToggleTreeViewVisib.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
+ this.button_ToggleTreeViewVisib.Location = new System.Drawing.Point(625, 18);
+ this.button_ToggleTreeViewVisib.Name = "button_ToggleTreeViewVisib";
+ this.button_ToggleTreeViewVisib.Size = new System.Drawing.Size(129, 22);
+ this.button_ToggleTreeViewVisib.TabIndex = 2;
+ this.button_ToggleTreeViewVisib.Text = "Toggle Visibility";
+ this.button_ToggleTreeViewVisib.UseVisualStyleBackColor = true;
+ this.button_ToggleTreeViewVisib.Click += new System.EventHandler(this.button_ToggleTreeViewVisib_Click);
+ //
+ // SyntaxTreeView
+ //
+ this.SyntaxTreeView.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.SyntaxTreeView.Location = new System.Drawing.Point(6, 46);
+ this.SyntaxTreeView.Name = "SyntaxTreeView";
+ this.SyntaxTreeView.Size = new System.Drawing.Size(748, 369);
+ this.SyntaxTreeView.TabIndex = 0;
+ //
+ // tabPage_CodeGeneration
+ //
+ this.tabPage_CodeGeneration.Controls.Add(this.groupBox4);
+ this.tabPage_CodeGeneration.Location = new System.Drawing.Point(4, 22);
+ this.tabPage_CodeGeneration.Name = "tabPage_CodeGeneration";
+ this.tabPage_CodeGeneration.Size = new System.Drawing.Size(777, 434);
+ this.tabPage_CodeGeneration.TabIndex = 3;
+ this.tabPage_CodeGeneration.Text = "Code generation";
+ this.tabPage_CodeGeneration.UseVisualStyleBackColor = true;
+ //
+ // groupBox4
+ //
+ this.groupBox4.Controls.Add(this.button_SimpleButton);
+ this.groupBox4.Controls.Add(this.button_AnotherButton);
+ this.groupBox4.Controls.Add(this.treeView1);
+ this.groupBox4.Location = new System.Drawing.Point(8, 6);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size(760, 421);
+ this.groupBox4.TabIndex = 2;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "Code generation";
+ //
+ // button_SimpleButton
+ //
+ this.button_SimpleButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
+ this.button_SimpleButton.Location = new System.Drawing.Point(484, 18);
+ this.button_SimpleButton.Name = "button_SimpleButton";
+ this.button_SimpleButton.Size = new System.Drawing.Size(129, 22);
+ this.button_SimpleButton.TabIndex = 5;
+ this.button_SimpleButton.Text = "Simple Button";
+ this.button_SimpleButton.UseVisualStyleBackColor = true;
+ //
+ // button_AnotherButton
+ //
+ this.button_AnotherButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(254)));
+ this.button_AnotherButton.Location = new System.Drawing.Point(625, 18);
+ this.button_AnotherButton.Name = "button_AnotherButton";
+ this.button_AnotherButton.Size = new System.Drawing.Size(129, 22);
+ this.button_AnotherButton.TabIndex = 4;
+ this.button_AnotherButton.Text = "Another Button";
+ this.button_AnotherButton.UseVisualStyleBackColor = true;
+ //
+ // treeView1
+ //
+ this.treeView1.Location = new System.Drawing.Point(6, 46);
+ this.treeView1.Name = "treeView1";
+ this.treeView1.Size = new System.Drawing.Size(748, 369);
+ this.treeView1.TabIndex = 0;
//
// MainForm
//
@@ -198,12 +329,16 @@ private void InitializeComponent()
this.Name = "MainForm";
this.Text = "Lexical analyzer";
this.tabControl1.ResumeLayout(false);
- this.tabPage_sourceFile.ResumeLayout(false);
+ this.tabPage_SourceFile.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.tabPage_LexicalTable.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dataGridView_table)).EndInit();
+ this.tabPage_SyntaxTree.ResumeLayout(false);
+ this.groupBox3.ResumeLayout(false);
+ this.tabPage_CodeGeneration.ResumeLayout(false);
+ this.groupBox4.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -211,7 +346,7 @@ private void InitializeComponent()
#endregion
private System.Windows.Forms.TabControl tabControl1;
- private System.Windows.Forms.TabPage tabPage_sourceFile;
+ private System.Windows.Forms.TabPage tabPage_SourceFile;
private System.Windows.Forms.TabPage tabPage_LexicalTable;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button button_openFile;
@@ -219,8 +354,19 @@ private void InitializeComponent()
private System.Windows.Forms.TextBox textBox_FileViewer;
private System.Windows.Forms.DataGridView dataGridView_table;
private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.TabPage tabPage_SyntaxTree;
+ private System.Windows.Forms.GroupBox groupBox3;
+ private System.Windows.Forms.TreeView SyntaxTreeView;
private System.Windows.Forms.DataGridViewTextBoxColumn Number;
- private System.Windows.Forms.DataGridViewTextBoxColumn Type;
private System.Windows.Forms.DataGridViewTextBoxColumn Value;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Type;
+ private System.Windows.Forms.TabPage tabPage_CodeGeneration;
+ private System.Windows.Forms.Button button_ToggleTreeViewVisib;
+ private System.Windows.Forms.GroupBox groupBox4;
+ private System.Windows.Forms.TreeView treeView1;
+ private System.Windows.Forms.Button button_ShowDeepestTreeView;
+ private System.Windows.Forms.Button button_SimpleButton;
+ private System.Windows.Forms.Button button_AnotherButton;
+ private System.Windows.Forms.Button button_RegenerateTreeView;
}
}
\ No newline at end of file
diff --git a/MainForm.cs b/MainForm.cs
index ce7c75e..e7572c0 100644
--- a/MainForm.cs
+++ b/MainForm.cs
@@ -1,5 +1,7 @@
using LexicalAnalyzer.LexicalAnalyzer.Source;
+using LexicalAnalyzer.Source;
using System;
+using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
@@ -8,9 +10,29 @@ namespace LexicalAnalyzer
{
public partial class MainForm : Form
{
+ private const bool DEV_MODE = true;
+ private bool syntaxTreeIsExpanded = false;
+
+ private ArrayList list = new ArrayList();
+
public MainForm()
{
InitializeComponent();
+
+ if (DEV_MODE)
+ {
+ textBox_FilePath.Text = "X:\\Dev\\Projects\\GUMRF\\LexicalAnalyzer\\Tests\\Normal code Simple.txt";
+ if (File.Exists(textBox_FilePath.Text))
+ {
+ using (StreamReader reader = new StreamReader(textBox_FilePath.Text))
+ {
+ string fileContent = reader.ReadToEnd();
+ textBox_FileViewer.Text = fileContent;
+ }
+
+ fillTabsContent();
+ }
+ }
}
private void button_openFile_Click(object sender, EventArgs e)
@@ -34,7 +56,7 @@ private void button_openFile_Click(object sender, EventArgs e)
textBox_FilePath.Text = filePath;
textBox_FileViewer.Text = fileContent;
}
- addListLexToDataTableView();
+ fillTabsContent();
}
}
}
@@ -45,8 +67,49 @@ private void button_openFile_Click(object sender, EventArgs e)
}
catch (Exception exception)
{
- MessageBox.Show(exception.Message, "Unexpected exception", MessageBoxButtons.OK);
- throw;
+ MessageBox.Show(exception.Message, this.GetType().Name, MessageBoxButtons.OK);
+ }
+ }
+
+ private void button_ToggleTreeViewVisib_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (syntaxTreeIsExpanded)
+ {
+ SyntaxTreeView?.CollapseAll();
+ }
+ else
+ {
+ SyntaxTreeView?.ExpandAll();
+ }
+ syntaxTreeIsExpanded = !syntaxTreeIsExpanded;
+ }
+ catch (Exception exception)
+ {
+ MessageBox.Show(exception.Message, this.GetType().Name, MessageBoxButtons.OK);
+ }
+ }
+
+ private void button_ShowDeepestTreeView_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ GetDeeperLevel(SyntaxTreeView?.Nodes[0]);
+ list.Sort();
+ }
+ catch (Exception exception)
+ {
+ MessageBox.Show(exception.Message, this.GetType().Name, MessageBoxButtons.OK);
+ }
+ }
+
+ private void GetDeeperLevel(TreeNode node)
+ {
+ for (int i = 0; i < node.Nodes.Count; i++)
+ {
+ GetDeeperLevel(node.Nodes[i]);
+ list.Add(node.Nodes[i].Level);
}
}
@@ -54,30 +117,59 @@ private void textBox_FilePath_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (Int32)(Keys.Enter))
{
- if (File.Exists(textBox_FilePath.Text))
+ try
{
- using (StreamReader reader = new StreamReader(textBox_FilePath.Text))
+ if (File.Exists(textBox_FilePath.Text))
{
- string fileContent = reader.ReadToEnd();
- textBox_FileViewer.Text = fileContent;
+ using (StreamReader reader = new StreamReader(textBox_FilePath.Text))
+ {
+ string fileContent = reader.ReadToEnd();
+ textBox_FileViewer.Text = fileContent;
+ }
+ fillTabsContent();
}
- addListLexToDataTableView();
+ }
+ catch (Exception exception)
+ {
+ MessageBox.Show(exception.Message, this.GetType().Name, MessageBoxButtons.OK);
+ throw;
}
}
}
- private void addListLexToDataTableView()
+ private void fillTabsContent()
{
- dataGridView_table.Rows.Clear();
-
- // Transferring data to the method and then analyzing it
- Analyzer lexicAnalyzer = new Analyzer();
- List lexicList = lexicAnalyzer.getLexemesList(textBox_FileViewer.Text);
+ Lexer lexicalAnalyzer = new Lexer();
+ Parser parser = new Parser();
+ // Fill in the table of lexemes
+ dataGridView_table?.Rows.Clear();
+ List lexicList = lexicalAnalyzer.getLexemesList(textBox_FileViewer.Text);
+
for (int i = 0; i < lexicList.Count; i++)
{
- dataGridView_table.Rows.Add(i, lexicList[i].lexemWord, lexicList[i].lexemType);
+ dataGridView_table.Rows.Add(i + 1, lexicList[i].word, lexicList[i].type);
+ }
+
+ // Build a syntax tree
+ parser.GenerateAbstractSyntaxTree(SyntaxTreeView, lexicList);
+ }
+
+ private void button_RegenerateTreeView_Click(object sender, EventArgs e)
+ {
+ if (File.Exists(textBox_FilePath.Text))
+ {
+ using (StreamReader reader = new StreamReader(textBox_FilePath.Text))
+ {
+ string fileContent = reader.ReadToEnd();
+ textBox_FileViewer.Text = fileContent;
+ }
+
+ fillTabsContent();
+ SyntaxTreeView?.ExpandAll();
+ syntaxTreeIsExpanded = true;
}
+
}
}
}
diff --git a/MainForm.resx b/MainForm.resx
index c6eb12d..4643a61 100644
--- a/MainForm.resx
+++ b/MainForm.resx
@@ -120,10 +120,10 @@
True
-
+
True
-
+
True
\ No newline at end of file
diff --git a/Source/Lex.cs b/Source/Lex.cs
index 8622528..24377cf 100644
--- a/Source/Lex.cs
+++ b/Source/Lex.cs
@@ -1,21 +1,40 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace LexicalAnalyzer.LexicalAnalyzer.Source
+namespace LexicalAnalyzer.LexicalAnalyzer.Source
{
+ // TODO: Replace text type with enum?
+ // This may be more convenient than the current implementation.
+ // Address/search by type (.Semicolon, ,Variable) , but display static name in DataGridTable.
+
+
+
public class Lex
{
- public readonly string lexemType;
- public readonly string lexemWord;
-
- public Lex(string lexemType, string lexemWord)
+ public readonly Type type;
+ public readonly string word;
+
+ public enum Type
{
- this.lexemType = lexemType;
- this.lexemWord = lexemWord;
+ Assign, // :=
+ Colon, // :
+ Comment_Open, // {
+ Comment_Close, // }
+ End, // .
+ Logical_AND, // and
+ Logical_NOT, // not
+ Logical_OR, // or
+ Logical_XOR, // xor
+ Parenthesis, // ()
+ Semicolon, // ;
+ Condition, // true/false
+ Constant, // const
+ Variable, // variable
+ Null, // null-value
}
+
+ public Lex(Type _lexemType, string _lexemWord)
+ {
+ this.type = _lexemType;
+ this.word = _lexemWord;
+ }
+
}
}
diff --git a/Source/Analyzer.cs b/Source/Lexer.cs
similarity index 73%
rename from Source/Analyzer.cs
rename to Source/Lexer.cs
index b917957..9a4852c 100644
--- a/Source/Analyzer.cs
+++ b/Source/Lexer.cs
@@ -15,13 +15,21 @@ internal class ServiceWordsDictionary
/// This dictionary contains a list of all service words.
/// For example: "Condition" : "true", "false"
///
- public readonly Dictionary> serviceWords = new Dictionary>()
+ public readonly Dictionary> serviceWords = new Dictionary>()
{
- {"Condition", new List { "if", "else", } },
- {"Statement", new List{ "true", "false", } },
- {"Logical", new List {"xor", "or", "and", "not", } },
- {"Service", new List {"program", "var", "begin", "write", "writeln", "for", "to", "do", "random", "randomize", "end"} },
- {"Variable type", new List {"integer", "boolean", } }
+ {Lex.Type.Condition, new List{ "true", "false", } },
+ {Lex.Type.Logical_XOR, new List {"xor"} },
+ {Lex.Type.Logical_AND, new List {"and"} },
+ {Lex.Type.Logical_NOT, new List {"not"} },
+ {Lex.Type.Logical_OR, new List {"or"} },
+ };
+
+ public readonly Dictionary> serviceDelimiters = new Dictionary>()
+ {
+ {Lex.Type.Semicolon, new List{";"} },
+ {Lex.Type.Colon, new List{":"} },
+ {Lex.Type.End, new List{"."} },
+ {Lex.Type.Parenthesis, new List{")","("} }
};
///
@@ -30,12 +38,12 @@ internal class ServiceWordsDictionary
/// The word to be found
/// Returns the name of the category in which the passed word was found.
/// If no word is found, it returns null.
- public string FindServiceWordCategory(string word)
+ public Lex.Type FindServiceCategory(string word, Dictionary> serviceDict)
{
// Read every key and get his values
- foreach (KeyValuePair> keyValuePair in serviceWords)
+ foreach (KeyValuePair> keyValuePair in serviceDict)
{
- string key = keyValuePair.Key;
+ Lex.Type key = keyValuePair.Key;
List values = keyValuePair.Value;
foreach (var serviceWord in values)
@@ -43,25 +51,22 @@ public string FindServiceWordCategory(string word)
if (serviceWord == word) return key;
}
}
- return null;
+ return Lex.Type.Null;
}
- public bool isDelimiter(string symbol)
- {
- List delimiters = new List()
- {
- ".", ";", ",", "(", ")", "+", "-", "*", "/", "=", ">", "<",
- };
- return delimiters.Contains(symbol);
- }
}
- internal class Analyzer
+ internal class Lexer
{
+ ///
+ /// Looking for "end." at the end of the program?
+ ///
+ private bool waitEndOfProgram = false;
+
private enum States { SCANNING, IS_WORD, IS_CONST, IS_DELIMITER, IS_ASSIGN, IS_COMMENT, ERROR, FINISHED, };
private States _state;
-
- private ServiceWordsDictionary _serviceWordsDict = new ServiceWordsDictionary();
+
+ private ServiceWordsDictionary _serviceDict = new ServiceWordsDictionary();
public readonly List lexemesList = new List();
// File reader:
@@ -96,10 +101,17 @@ private void GetNextChar()
// If no new characters are found in the string:
if (countOfNewSymbols == 0)
{
- // Most likely, the search for "end." is a task of the syntax analyzer,
- // so we can replace it with States.FINISHED.
- _state = States.ERROR;
- error_message = "The file is read to the end, but \"end.\" never came up.";
+ if (!waitEndOfProgram)
+ {
+ _state = States.FINISHED;
+ }
+ else
+ {
+ // Most likely, the search for "end." is a task of the syntax analyzer,
+ // so we can replace it with States.FINISHED.
+ _state = States.ERROR;
+ error_message = "The file is read to the end, but \"end.\" never came up.";
+ }
}
}
@@ -117,9 +129,9 @@ private void AddToBuffer(char symbol)
bufferOfChars += symbol;
}
- private void AddToLexemesList(List _lexemesList, string wordType, string wordBuffer)
+ private void AddToLexemesList(List _lexemesList, Lex.Type lexType, string wordBuffer)
{
- _lexemesList.Add(new Lex(wordType, wordBuffer));
+ _lexemesList.Add(new Lex(lexType, wordBuffer));
}
public List getLexemesList(string text)
@@ -144,7 +156,7 @@ private void AnalyzeLexemes(string text)
{
GetNextChar();
}
- else if (char.IsLetter(currentChar[0]))
+ else if (char.IsLetter(currentChar[0]) || currentChar[0] == '_')
{
ClearBuffer();
AddToBuffer(currentChar[0]);
@@ -174,7 +186,7 @@ private void AnalyzeLexemes(string text)
}
else if (currentChar[0] == '.')
{
- AddToLexemesList(lexemesList, "End of program", currentChar[0].ToString());
+ AddToLexemesList(lexemesList, Lex.Type.End, currentChar[0].ToString());
_state = States.FINISHED;
}
else
@@ -185,24 +197,24 @@ private void AnalyzeLexemes(string text)
// This state tries to find a service word equal to the word in the buffer
case States.IS_WORD:
- if (char.IsLetterOrDigit(currentChar[0]))
+ if (char.IsLetterOrDigit(currentChar[0]) || currentChar[0] == '_')
{
AddToBuffer(currentChar[0]);
GetNextChar();
}
else
{
- string serviceWordType = _serviceWordsDict.FindServiceWordCategory(bufferOfChars);
+ Lex.Type serviceWordType = _serviceDict.FindServiceCategory(bufferOfChars, _serviceDict.serviceWords);
// Found service word from the dictionary
- if (serviceWordType != null)
+ if (serviceWordType != Lex.Type.Null)
{
AddToLexemesList(lexemesList, serviceWordType, bufferOfChars);
}
- // If the word is not found in the dictionary, write it as "Variable"
else
{
- AddToLexemesList(lexemesList, "Variable", bufferOfChars);
+ //If the word is not found in the dictionary, write it as "Variable"
+ AddToLexemesList(lexemesList, Lex.Type.Variable, bufferOfChars);
}
ClearBuffer();
_state = States.SCANNING;
@@ -219,14 +231,14 @@ private void AnalyzeLexemes(string text)
}
else if (char.IsLetter(currentChar[0]))
{
- _state = States.ERROR;
error_message = "An invalid character was found: a letter.\n" +
"No letters are allowed in constants!";
+ _state = States.ERROR;
break;
}
else
{
- AddToLexemesList(lexemesList, "Constant", bufferOfChars);
+ AddToLexemesList(lexemesList, Lex.Type.Constant, bufferOfChars);
ClearBuffer();
_state = States.SCANNING;
}
@@ -235,15 +247,20 @@ private void AnalyzeLexemes(string text)
case States.IS_DELIMITER:
ClearBuffer();
AddToBuffer(currentChar[0]);
- if (_serviceWordsDict.isDelimiter(bufferOfChars))
+
+ Lex.Type serviceDelimiters = _serviceDict.FindServiceCategory(bufferOfChars, _serviceDict.serviceDelimiters);
+
+ // Found service word from the dictionary
+ if (serviceDelimiters != Lex.Type.Null)
{
- AddToLexemesList(lexemesList, "Delimiter", currentChar[0].ToString());
+ AddToLexemesList(lexemesList, serviceDelimiters, bufferOfChars);
ClearBuffer();
_state = States.SCANNING;
GetNextChar();
}
else
{
+ error_message = $"The \"IS_DELIMITER\" state is active, but the current symbol \"{bufferOfChars}\" is not delimiter!";
_state = States.ERROR;
}
break;
@@ -252,13 +269,13 @@ private void AnalyzeLexemes(string text)
if (currentChar[0] == '=')
{
AddToBuffer(currentChar[0]);
- AddToLexemesList(lexemesList, "Assign", bufferOfChars);
+ AddToLexemesList(lexemesList, Lex.Type.Assign, bufferOfChars);
ClearBuffer();
GetNextChar();
}
else
{
- AddToLexemesList(lexemesList, "Type delimiter", bufferOfChars);
+ AddToLexemesList(lexemesList, Lex.Type.Colon, bufferOfChars);
}
_state = States.SCANNING;
break;
@@ -266,7 +283,7 @@ private void AnalyzeLexemes(string text)
case States.IS_COMMENT:
bool bClosingBlockFound = false;
- AddToLexemesList(lexemesList, "Start of comment block", bufferOfChars);
+ AddToLexemesList(lexemesList, Lex.Type.Comment_Open, bufferOfChars);
ClearBuffer();
while (stringReader.Peek() >= 0)
@@ -284,13 +301,13 @@ private void AnalyzeLexemes(string text)
_state = States.ERROR;
}
- AddToLexemesList(lexemesList, "End of comment block", currentChar[0].ToString());
+ AddToLexemesList(lexemesList, Lex.Type.Comment_Close, currentChar[0].ToString());
_state = States.SCANNING;
GetNextChar();
break;
case States.ERROR:
- MessageBox.Show(error_message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show(error_message, "State error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
_state = States.FINISHED;
break;
@@ -301,7 +318,7 @@ private void AnalyzeLexemes(string text)
}
catch (Exception _err)
{
- MessageBox.Show(_err.Message, "Exception", MessageBoxButtons.OK);
+ MessageBox.Show(_err.Message, "{FSM} Exception", MessageBoxButtons.OK);
throw;
}
diff --git a/Source/Parser.cs b/Source/Parser.cs
new file mode 100644
index 0000000..3fc3e45
--- /dev/null
+++ b/Source/Parser.cs
@@ -0,0 +1,120 @@
+using LexicalAnalyzer.LexicalAnalyzer.Source;
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace LexicalAnalyzer.Source
+{
+ class Parser
+ {
+ private readonly ParserRules rules = new ParserRules();
+
+ public void GenerateAbstractSyntaxTree(TreeView treeView, List lexes)
+ {
+ try
+ {
+ treeView.Nodes.Clear();
+ treeView.Nodes.Add("E");
+
+ TreeNode rootTreeNode = treeView.Nodes[0];
+ TreeNode blockTreeNode = null;
+ int blockExprIndex = 0;
+ int blockBeginIndex = 0;
+
+ // Iterate through the list of lexemes, looking at each
+ for (int blockEndIndex = blockBeginIndex; blockEndIndex < lexes.Count; blockEndIndex++)
+ {
+ // If a syntactically correct string ending with a semicolon is found
+ if (lexes[blockEndIndex].type == Lex.Type.Semicolon)
+ {
+ rootTreeNode.Nodes.Add("E");
+
+ // The root block of the expression is temporarily stored here
+ blockTreeNode = rootTreeNode.Nodes[blockExprIndex];
+
+ GenerateTreeNodes(blockTreeNode, lexes, blockBeginIndex, blockEndIndex);
+ blockTreeNode.Nodes.Add(";");
+ blockBeginIndex = blockEndIndex + 1;
+
+ // Move to the next root block of the expression
+ blockExprIndex++;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show(e.Message, this.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private void GenerateTreeNodes(TreeNode root, List lexes, int _begin, int _end)
+ {
+ for (int i = _begin; i <= _end; i++)
+ {
+ // Terminal types (true, not, variable, symbols, etc)
+ if (lexes[i].type == Lex.Type.Variable) AddChildNode(root, lexes[i].word);
+ else if (lexes[i].type == Lex.Type.Condition) AddChildNode(root, lexes[i].word);
+ else if (isLogicalType(lexes[i].type)) root.Nodes.Add(lexes[i].word);
+
+ // Can be a nested expressions
+ else if (lexes[i].word == "(")
+ {
+ TreeNode parenthesisExp = root.Nodes.Add("E");
+ parenthesisExp.Nodes.Add("(");
+
+ TreeNode temporary = parenthesisExp.Nodes.Add("E");
+ int parenthesisEnd = i;
+
+ for (; parenthesisEnd < _end; parenthesisEnd++)
+ {
+ if (lexes[parenthesisEnd].word == ")")
+ {
+ GenerateTreeNodes(temporary, lexes, i + 1, parenthesisEnd);
+ }
+ }
+ i = parenthesisEnd;
+ parenthesisExp.Nodes.Add(")");
+ }
+
+ // It can be either a nested expression or a terminal type
+ else if (lexes[i].type == Lex.Type.Assign)
+ {
+ root.Nodes.Add(":=");
+
+ // If there are more than 2 tokens left in the string (a difficult expression is found)
+ if (_end - i > 2)
+ {
+ TreeNode expression = root.Nodes.Add("E");
+ GenerateTreeNodes(expression, lexes, i + 1, _end);
+ return;
+ }
+ }
+ }
+ }
+
+
+ ///
+ /// Adds a child node with the specified name
+ ///
+ /// The parent node to which to add a new node
+ /// Name of added node
+ private void AddChildNode(TreeNode parent, string name)
+ {
+ TreeNode temporary = parent.Nodes.Add("E");
+ temporary.Nodes.Add(name);
+ }
+
+ private bool isLogicalType(Lex.Type type)
+ {
+ if (type == Lex.Type.Logical_AND || type == Lex.Type.Logical_XOR ||
+ type == Lex.Type.Logical_OR || type == Lex.Type.Logical_NOT)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/Source/ParserRules.cs b/Source/ParserRules.cs
new file mode 100644
index 0000000..41d2b8a
--- /dev/null
+++ b/Source/ParserRules.cs
@@ -0,0 +1,96 @@
+using LexicalAnalyzer.LexicalAnalyzer.Source;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace LexicalAnalyzer.Source
+{
+ class ParserRulesPriorities
+ {
+ public Dictionary RulesPriorities = new Dictionary()
+ {
+ {0, Lex.Type.Semicolon },
+ {1, Lex.Type.Parenthesis },
+ {2, Lex.Type.Logical_NOT },
+ {3, Lex.Type.Logical_AND },
+ {4, Lex.Type.Logical_XOR },
+ {5, Lex.Type.Logical_OR },
+ {6, Lex.Type.Condition },
+ {7, Lex.Type.Assign },
+ {8, Lex.Type.Variable },
+ {9, Lex.Type.Null },
+ };
+ }
+
+ class ParserRules
+ {
+ // TODO: Rule_IsVariable (List lexesList, int currentLexIndex) { ... }
+ public bool Rule_EndsOnSemicolon(string text)
+ {
+ string pattern = @";$";
+ return Regex.IsMatch(text, pattern);
+ }
+
+ public bool Rule_IsVariable(string text)
+ {
+ string pattern = "Variable";
+ return pattern == text;
+ }
+
+ public bool Rule_IsAssign(string text)
+ {
+ string pattern = @":=";
+ return Regex.IsMatch(text, pattern);
+ }
+
+ public bool Rule_IsSemicolon(string text)
+ {
+ return text == ";";
+ }
+
+ public bool Rule_IsStatement(string text)
+ {
+ return text == "Statement";
+ }
+
+ ///
+ /// AND, OR, XOR
+ ///
+ ///
+ ///
+ public bool Rule_IsBinaryOperand(string text)
+ {
+ return text == "and" || text == "or" || text == "xor";
+ }
+
+ ///
+ /// NOT
+ ///
+ ///
+ ///
+ public bool Rule_IsUnaryOperand(string text)
+ {
+ return text == "not";
+ }
+
+ public bool Rule_IsOpeningParenthesis(string text)
+ {
+ return text == "(";
+ }
+
+ public bool Rule_IsClosingParenthesis(string text)
+ {
+ return text == ")";
+ }
+
+ ///
+ /// Binary-AND/OR/XOR, unary-NOT, (
+ ///
+ ///
+ ///
+ public bool Rule_IsExpression(string text)
+ {
+ return Rule_IsBinaryOperand(text) || Rule_IsUnaryOperand(text) || Rule_IsOpeningParenthesis(text);
+ }
+
+ }
+}
diff --git a/Tests/AST.drawio.png b/Tests/AST.drawio.png
new file mode 100644
index 0000000..efeb4e1
Binary files /dev/null and b/Tests/AST.drawio.png differ
diff --git a/Tests/AST.png b/Tests/AST.png
new file mode 100644
index 0000000..fd5df78
Binary files /dev/null and b/Tests/AST.png differ
diff --git a/Tests/Normal code - Binary.txt b/Tests/Normal code - Binary.txt
new file mode 100644
index 0000000..12be583
--- /dev/null
+++ b/Tests/Normal code - Binary.txt
@@ -0,0 +1,12 @@
+program bool;
+ var x, y: boolean;
+begin
+ x := true;
+ y := x and true;
+ y := false1;
+ y := true | false;
+ if x = true then
+ writeln(x);
+
+end.
+
\ No newline at end of file
diff --git a/Tests/Normal code Simple 2.txt b/Tests/Normal code Simple 2.txt
new file mode 100644
index 0000000..7b54fc0
--- /dev/null
+++ b/Tests/Normal code Simple 2.txt
@@ -0,0 +1,7 @@
+
+true_val := true;
+false_val := false;
+
+val_1 := not (true_val and false_val);
+
+val_2 := true or not (true_val xor false);
\ No newline at end of file
diff --git a/Tests/Normal code Simple.txt b/Tests/Normal code Simple.txt
new file mode 100644
index 0000000..ed1d4d5
--- /dev/null
+++ b/Tests/Normal code Simple.txt
@@ -0,0 +1,4 @@
+value_1 := true;
+value_2 := false;
+
+value_3 := false or (not true);
\ No newline at end of file
diff --git a/Tests/Normal code.txt b/Tests/Normal code.txt
index af94b2d..0de0e65 100644
--- a/Tests/Normal code.txt
+++ b/Tests/Normal code.txt
@@ -1,12 +1,21 @@
program bool;
var x, y: boolean;
begin
+ {a1 := true;
+ b1 := false;
+ c1 := false;}
+
x := true;
y := false;
- y := false1;
+ z := false;
+ z1 := true;
+ y := x or true and false xor y not z not y;
+
+ { Пример плохого кода }
+ {y := xor z andd trues not x or y or z1;}
+
if x = true then
writeln(x);
-end.
-
\ No newline at end of file
+end.
\ No newline at end of file
diff --git a/Tests/One line code.txt b/Tests/One line code.txt
deleted file mode 100644
index c1856a4..0000000
--- a/Tests/One line code.txt
+++ /dev/null
@@ -1 +0,0 @@
-program bool;var x,y:boolean;begin x:=trrue;y:=false;y:=false1;if x=true then writeln (x);end.
\ No newline at end of file
diff --git a/Tests/PriorityTable.drawio.png b/Tests/PriorityTable.drawio.png
new file mode 100644
index 0000000..a6796e6
Binary files /dev/null and b/Tests/PriorityTable.drawio.png differ