From 42cd6a8c49ee457c4c32c05c1e846c75f2247fa1 Mon Sep 17 00:00:00 2001 From: PocketMiner82 Date: Fri, 12 Apr 2024 13:50:56 +0200 Subject: [PATCH] feat: add snippet blocks to autocomplete menu --- .editorconfig | 8 -- pseudocodeIde/Extensions.cs | 2 +- pseudocodeIde/PseudocodeIDEForm.Designer.cs | 4 +- pseudocodeIde/PseudocodeIDEForm.cs | 77 ++++++------ pseudocodeIde/interpreter/Interpreter.cs | 3 +- .../CSharpCodeManager.cs | 4 +- .../TemplateCodeOutput.cs | 2 +- pseudocodeIde/interpreter/parser/Parser.cs | 5 +- .../pseudocode/PseudocodeAutocompleteItem.cs | 50 ++++++++ .../pseudocode/PseudocodeKeywords.cs | 112 ++++++++++++++++++ .../interpreter/pseudocode/PseudocodeType.cs | 96 +++++++++++++++ .../pseudocode/PseudocodeTypeDictionary.cs | 30 +++++ .../{scanner => pseudocode}/Token.cs | 2 +- .../{scanner => pseudocode}/TokenType.cs | 2 +- pseudocodeIde/interpreter/scanner/Scanner.cs | 74 +----------- ...gLexer.cs => SyntaxHighlightingScanner.cs} | 6 +- pseudocodeIde/pseudocodeIde.csproj | 3 +- 17 files changed, 350 insertions(+), 130 deletions(-) rename pseudocodeIde/interpreter/{parser => csharpcode}/CSharpCodeManager.cs (98%) rename pseudocodeIde/interpreter/{parser => csharpcode}/TemplateCodeOutput.cs (99%) create mode 100644 pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs create mode 100644 pseudocodeIde/interpreter/pseudocode/PseudocodeKeywords.cs create mode 100644 pseudocodeIde/interpreter/pseudocode/PseudocodeType.cs create mode 100644 pseudocodeIde/interpreter/pseudocode/PseudocodeTypeDictionary.cs rename pseudocodeIde/interpreter/{scanner => pseudocode}/Token.cs (97%) rename pseudocodeIde/interpreter/{scanner => pseudocode}/TokenType.cs (96%) rename pseudocodeIde/interpreter/scanner/{SyntaxHighlightingLexer.cs => SyntaxHighlightingScanner.cs} (98%) diff --git a/.editorconfig b/.editorconfig index c7fe5e2..a60a4f4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -207,10 +207,6 @@ dotnet_naming_rule.constant_should_be_capslock.severity = warning dotnet_naming_rule.constant_should_be_capslock.symbols = constant dotnet_naming_rule.constant_should_be_capslock.style = capslock -dotnet_naming_rule.readonly_should_be_capslock.severity = warning -dotnet_naming_rule.readonly_should_be_capslock.symbols = readonly -dotnet_naming_rule.readonly_should_be_capslock.style = capslock - dotnet_naming_rule.private_or_internal_field_should_be_camelcase_with_underscore_prefix.severity = warning dotnet_naming_rule.private_or_internal_field_should_be_camelcase_with_underscore_prefix.symbols = private_or_internal_field dotnet_naming_rule.private_or_internal_field_should_be_camelcase_with_underscore_prefix.style = camelcase_with_underscore_prefix @@ -245,10 +241,6 @@ dotnet_naming_symbols.constant.applicable_kinds = namespace, property, field, ev dotnet_naming_symbols.constant.applicable_accessibilities = * dotnet_naming_symbols.constant.required_modifiers = const -dotnet_naming_symbols.readonly.applicable_kinds = namespace, property, field, event, parameter, local, class, struct, interface, enum, delegate, method, local_function -dotnet_naming_symbols.readonly.applicable_accessibilities = * -dotnet_naming_symbols.readonly.required_modifiers = readonly - # Benennungsstile dotnet_naming_style.pascal_case.required_prefix = diff --git a/pseudocodeIde/Extensions.cs b/pseudocodeIde/Extensions.cs index 40dff67..91defcd 100644 --- a/pseudocodeIde/Extensions.cs +++ b/pseudocodeIde/Extensions.cs @@ -9,7 +9,7 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY -using pseudocodeIde.interpreter; +using pseudocode_ide.interpreter.pseudocode; using System; using System.Collections.Generic; using System.IO; diff --git a/pseudocodeIde/PseudocodeIDEForm.Designer.cs b/pseudocodeIde/PseudocodeIDEForm.Designer.cs index edb6585..3c37f77 100644 --- a/pseudocodeIde/PseudocodeIDEForm.Designer.cs +++ b/pseudocodeIde/PseudocodeIDEForm.Designer.cs @@ -308,9 +308,11 @@ private void InitializeComponent() this.autoCompleteMenu.AllowsTabKey = true; this.autoCompleteMenu.AppearInterval = 50; this.autoCompleteMenu.Colors = ((AutocompleteMenuNS.Colors)(resources.GetObject("autoCompleteMenu.Colors"))); - this.autoCompleteMenu.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F); + this.autoCompleteMenu.Font = new System.Drawing.Font("Verdana", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.autoCompleteMenu.ImageList = null; this.autoCompleteMenu.Items = new string[0]; + this.autoCompleteMenu.MaximumSize = new System.Drawing.Size(250, 200); + this.autoCompleteMenu.MinFragmentLength = 1; this.autoCompleteMenu.TargetControlWrapper = null; // // PseudocodeIDEForm diff --git a/pseudocodeIde/PseudocodeIDEForm.cs b/pseudocodeIde/PseudocodeIDEForm.cs index e4447ef..975086b 100644 --- a/pseudocodeIde/PseudocodeIDEForm.cs +++ b/pseudocodeIde/PseudocodeIDEForm.cs @@ -13,6 +13,7 @@ using Microsoft.VisualBasic.FileIO; using Newtonsoft.Json; using pseudocode_ide; +using pseudocode_ide.interpreter.pseudocode; using pseudocode_ide.interpreter.scanner; using pseudocodeIde.interpreter; using ScintillaNET; @@ -39,7 +40,7 @@ public partial class PseudocodeIDEForm : Form /// /// do not update the undo stack when the last char is a letter from A-Z (case ignored), a number from 0-9 or a underscore /// - private readonly Regex NO_UPDATE_AFTER = new Regex(@"^[a-zA-Z0-9_äöüÄÖÜß]$", RegexOptions.Multiline); + private readonly Regex _noUpdateAfter = new Regex(@"^[a-zA-Z0-9_äöüÄÖÜß]$", RegexOptions.Multiline); /// /// the code currently in the textbox @@ -72,7 +73,7 @@ public string Code // undo and redo stacks private Stack _undoStack = new Stack(); - private readonly Stack REDO_STACK = new Stack(); + private readonly Stack _redoStack = new Stack(); /// /// the path where this file is saved @@ -87,12 +88,12 @@ public string Code /// /// The find and replace forms for the code textbox. /// - private readonly FindReplace FIND_REPLACE; + private readonly FindReplace _findReplace; /// /// The output form where the pseudocode execution logs are displayed. /// - private readonly OutputForm OUTPUT_FORM; + private readonly OutputForm _outputForm; /// /// The maximum length of the line number characters. @@ -103,9 +104,9 @@ public string Code public PseudocodeIDEForm() { InitializeComponent(); - OUTPUT_FORM = new OutputForm(this); - FIND_REPLACE = new FindReplace(codeTextBox); - FIND_REPLACE.KeyPressed += CodeTextBox_KeyDown; + _outputForm = new OutputForm(this); + _findReplace = new FindReplace(codeTextBox); + _findReplace.KeyPressed += CodeTextBox_KeyDown; ResetUndoRedo(); @@ -126,9 +127,9 @@ private void BuildAutocompleteMenu() List items = new List(); - foreach (string item in Scanner.KEYWORDS.Keys) + foreach (List keywordItems in PseudocodeKeywords.KEYWORDS.Values) { - items.Add(new SnippetAutocompleteItem(item) { ImageIndex = 1 }); + items.AddRange(keywordItems); } autoCompleteMenu.SetAutocompleteItems(items); @@ -163,21 +164,21 @@ private void ConfigureCodeTextBox() codeTextBox.Styles[Style.Default].Font = "Courier New"; codeTextBox.StyleClearAll(); - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_DEFAULT].ForeColor = Color.DarkGray; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_DEFAULT].ForeColor = Color.DarkGray; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_KEYWORD].ForeColor = Color.Blue; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_KEYWORD].Bold = true; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_KEYWORD].ForeColor = Color.Blue; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_KEYWORD].Bold = true; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_IDENTIFIER].ForeColor = Color.Black; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_IDENTIFIER].ForeColor = Color.Black; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_NUMBER].ForeColor = Color.Peru; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_NUMBER].ForeColor = Color.Peru; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_STRING].ForeColor = Color.OrangeRed; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_STRING].ForeColor = Color.OrangeRed; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_ESCAPE].ForeColor = Color.Orange; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_ESCAPE].Bold = true; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_ESCAPE].ForeColor = Color.Orange; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_ESCAPE].Bold = true; - codeTextBox.Styles[SyntaxHighlightingLexer.STYLE_COMMENT].ForeColor = Color.Green; + codeTextBox.Styles[SyntaxHighlightingScanner.STYLE_COMMENT].ForeColor = Color.Green; codeTextBox.LexerName = ""; codeTextBox.StyleNeeded += CodeTextBox_StyleNeeded; @@ -188,7 +189,7 @@ private void CodeTextBox_StyleNeeded(object sender, StyleNeededEventArgs e) int startPos = codeTextBox.GetEndStyled(); int endPos = e.Position; - SyntaxHighlightingLexer.Style(codeTextBox, startPos, endPos); + SyntaxHighlightingScanner.Style(codeTextBox, startPos, endPos); } private void WordWrapMenuItem_Click(object sender, EventArgs e) @@ -206,9 +207,9 @@ private void SingleEqualIsCompareOperatorMenuItem_Click(object sender, EventArgs private void PseudocodeIDE_FormClosing(object sender, FormClosingEventArgs e) { // main form won't close if child form is not disposed - if (!OUTPUT_FORM.IsDisposed) + if (!_outputForm.IsDisposed) { - OUTPUT_FORM.Close(); + _outputForm.Close(); Close(); return; } @@ -297,12 +298,12 @@ private void CodeTextBox_KeyDown(object sender, KeyEventArgs e) } else if (e.Shift && e.KeyCode == Keys.F3) { - FIND_REPLACE.Window.FindPrevious(); + _findReplace.Window.FindPrevious(); e.SuppressKeyPress = true; } else if (e.KeyCode == Keys.F3) { - FIND_REPLACE.Window.FindNext(); + _findReplace.Window.FindNext(); e.SuppressKeyPress = true; } } @@ -418,7 +419,7 @@ private void CodeTextBox_CharAdded(object sender, CharAddedEventArgs e) private void UserChangedSelection() { // ignore when we already undid something - if (REDO_STACK.Count != 0) + if (_redoStack.Count != 0) { _lastCursorPosition = codeTextBox.SelectionStart; return; @@ -666,7 +667,7 @@ private void OpenFile() private void ResetUndoRedo() { _undoStack.Clear(); - REDO_STACK.Clear(); + _redoStack.Clear(); _undoStack.Push(codeTextBox.Text); undoToolStripMenuItem.Enabled = false; redoToolStripMenuItem.Enabled = false; @@ -686,9 +687,9 @@ public void UpdateUndoStack(bool forceUpdate) // when user writes something new, the redo stack will be cleared undoToolStripMenuItem.Enabled = true; - if (REDO_STACK.Count != 0) + if (_redoStack.Count != 0) { - REDO_STACK.Clear(); + _redoStack.Clear(); redoToolStripMenuItem.Enabled = false; } @@ -710,14 +711,14 @@ public void UpdateUndoStack(bool forceUpdate) // don't update when the last char matches the NO_UPDATE_AFTER regex and the update is caused by text change. // also don't update, when the new undo text is already in the stack - if ((codeTextBox.SelectionStart > 1 && !forceUpdate && NO_UPDATE_AFTER.IsMatch(undoText.ElementAt(codeTextBox.SelectionStart - 2).ToString())) + if ((codeTextBox.SelectionStart > 1 && !forceUpdate && _noUpdateAfter.IsMatch(undoText.ElementAt(codeTextBox.SelectionStart - 2).ToString())) || _undoStack.Peek().Equals(undoText)) { return; } // again, make sure that the redo stack is empty - REDO_STACK.Clear(); + _redoStack.Clear(); // and update the undo stack, limit max undo size _undoStack.Push(undoText); @@ -727,9 +728,9 @@ public void UpdateUndoStack(bool forceUpdate) private void UndoToolStripMenuItem_Click(object sender, EventArgs e) { // put current text in redo if not already in there - if (REDO_STACK.Count == 0 || !REDO_STACK.Peek().Equals(codeTextBox.Text)) + if (_redoStack.Count == 0 || !_redoStack.Peek().Equals(codeTextBox.Text)) { - REDO_STACK.Push(codeTextBox.Text); + _redoStack.Push(codeTextBox.Text); redoToolStripMenuItem.Enabled = true; } @@ -771,16 +772,16 @@ private void RedoToolStripMenuItem_Click(object sender, EventArgs e) } // set the textbox text to the top item of the redo stack. also remove it from the stack - if (REDO_STACK.Count > 0) + if (_redoStack.Count > 0) { IgnoreTextChange = true; int oldSelectionStart = codeTextBox.SelectionStart; - codeTextBox.Text = REDO_STACK.Pop(); + codeTextBox.Text = _redoStack.Pop(); codeTextBox.SelectionStart = Math.Min(oldSelectionStart, codeTextBox.TextLength); } // no more things to redo - if (REDO_STACK.Count == 0) + if (_redoStack.Count == 0) { redoToolStripMenuItem.Enabled = false; } @@ -792,12 +793,12 @@ private void RedoToolStripMenuItem_Click(object sender, EventArgs e) private void FindMenuItem_Click(object sender, EventArgs e) { - FIND_REPLACE.ShowFind(); + _findReplace.ShowFind(); } private void ReplaceMenuItem_Click(object sender, EventArgs e) { - FIND_REPLACE.ShowReplace(); + _findReplace.ShowReplace(); } private void GoToMenuItem_Click(object sender, EventArgs e) @@ -811,12 +812,12 @@ private void GoToMenuItem_Click(object sender, EventArgs e) private void RunProgramMenuItem_Click(object sender, EventArgs e) { - OUTPUT_FORM.ShowAndRun(); + _outputForm.ShowAndRun(); } private void OpenOutputFormMenuItem_Click(object sender, EventArgs e) { - OUTPUT_FORM.Show(); + _outputForm.Show(); } // --------------------------------------------- diff --git a/pseudocodeIde/interpreter/Interpreter.cs b/pseudocodeIde/interpreter/Interpreter.cs index c509466..eb90575 100644 --- a/pseudocodeIde/interpreter/Interpreter.cs +++ b/pseudocodeIde/interpreter/Interpreter.cs @@ -9,8 +9,9 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY +using pseudocode_ide.interpreter.csharpcode; +using pseudocode_ide.interpreter.pseudocode; using pseudocodeIde.interpreter.logging; -using pseudocodeIde.interpreter.parser; using System; using System.Collections.Generic; using System.Threading; diff --git a/pseudocodeIde/interpreter/parser/CSharpCodeManager.cs b/pseudocodeIde/interpreter/csharpcode/CSharpCodeManager.cs similarity index 98% rename from pseudocodeIde/interpreter/parser/CSharpCodeManager.cs rename to pseudocodeIde/interpreter/csharpcode/CSharpCodeManager.cs index 7ad5e60..11b6c9d 100644 --- a/pseudocodeIde/interpreter/parser/CSharpCodeManager.cs +++ b/pseudocodeIde/interpreter/csharpcode/CSharpCodeManager.cs @@ -11,13 +11,15 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using pseudocodeIde; +using pseudocodeIde.interpreter; using pseudocodeIde.interpreter.logging; using System; using System.CodeDom.Compiler; using System.Reflection; using System.Threading; -namespace pseudocodeIde.interpreter.parser +namespace pseudocode_ide.interpreter.csharpcode { public class CSharpCodeManager { diff --git a/pseudocodeIde/interpreter/parser/TemplateCodeOutput.cs b/pseudocodeIde/interpreter/csharpcode/TemplateCodeOutput.cs similarity index 99% rename from pseudocodeIde/interpreter/parser/TemplateCodeOutput.cs rename to pseudocodeIde/interpreter/csharpcode/TemplateCodeOutput.cs index 552ef25..7aaf3c7 100644 --- a/pseudocodeIde/interpreter/parser/TemplateCodeOutput.cs +++ b/pseudocodeIde/interpreter/csharpcode/TemplateCodeOutput.cs @@ -1,4 +1,4 @@ -// +// // THIS FILE IS NOT COMPILED AS C# CODE. // IT IS AN EMBEDDED RESSOURCE. // diff --git a/pseudocodeIde/interpreter/parser/Parser.cs b/pseudocodeIde/interpreter/parser/Parser.cs index ad44032..ec938d3 100644 --- a/pseudocodeIde/interpreter/parser/Parser.cs +++ b/pseudocodeIde/interpreter/parser/Parser.cs @@ -9,11 +9,12 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY +using pseudocode_ide.interpreter.csharpcode; +using pseudocode_ide.interpreter.pseudocode; using pseudocodeIde.interpreter.logging; -using pseudocodeIde.interpreter.parser; using System.Collections.Generic; using System.Linq; -using static pseudocodeIde.interpreter.TokenType; +using static pseudocode_ide.interpreter.pseudocode.TokenType; namespace pseudocodeIde.interpreter { diff --git a/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs b/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs new file mode 100644 index 0000000..3c4e1c4 --- /dev/null +++ b/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs @@ -0,0 +1,50 @@ +// Pseudocode IDE - Execute Pseudocode for the German (BW) 2024 Abitur +// Copyright (C) 2024 PocketMiner82 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +using AutocompleteMenuNS; +using pseudocodeIde; +using ScintillaNET; + +namespace pseudocode_ide.interpreter.pseudocode +{ + /// + /// Represents an autocomplete item for pseudocode with custom behavior for replacing text. + /// + public class PseudocodeAutocompleteItem : SnippetAutocompleteItem + { + /// + /// Initializes a new instance of the class with the specified snippet and optional menu text. + /// + /// The snippet to be used for autocomplete. + /// The text to be displayed in the autocomplete menu. If null, the snippet is used. + public PseudocodeAutocompleteItem(string snippet, string menuText = null) : base(snippet) + { + if (menuText != null) + { + MenuText = menuText; + } + } + + /// + /// Gets the text to replace the current fragment with, adjusting for indentation based on the current line. + /// + /// The adjusted text for replacement. + public override string GetTextForReplace() + { + Scintilla scintilla = (Scintilla)Parent.TargetControlWrapper.TargetControl; + + string line = scintilla.Lines[scintilla.LineFromPosition(Parent.Fragment.Start)].Text; + string indents = new string('\t', line.GetIndentationLevel()); + + return Text.Replace("\n", $"\n{indents}"); + } + } +} diff --git a/pseudocodeIde/interpreter/pseudocode/PseudocodeKeywords.cs b/pseudocodeIde/interpreter/pseudocode/PseudocodeKeywords.cs new file mode 100644 index 0000000..e423320 --- /dev/null +++ b/pseudocodeIde/interpreter/pseudocode/PseudocodeKeywords.cs @@ -0,0 +1,112 @@ +// Pseudocode IDE - Execute Pseudocode for the German (BW) 2024 Abitur +// Copyright (C) 2024 PocketMiner82 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +using System.Collections.Generic; +using static pseudocode_ide.interpreter.pseudocode.TokenType; + +namespace pseudocode_ide.interpreter.pseudocode +{ + public static class PseudocodeKeywords + { + /// + /// All the defined keywords in pseudocode and their corresponding token. + /// + public static readonly PseudocodeTypeDictionary KEYWORDS = new PseudocodeTypeDictionary(); + + /// + /// Add the keywords contents to the readonly static list + /// + static PseudocodeKeywords() + { + // code block snippets + KEYWORDS.Add(new PseudocodeType("WENN", IF, "WENN ^\n\t\nENDE WENN")); + KEYWORDS.Add(new PseudocodeType("FALLS", SWITCH_PREFIX, "FALLS ^ GLEICH\n\tbedingung1:\n\t\t\n\tSONST:\n\t\t\nENDE FALLS")); + KEYWORDS.Add(new PseudocodeType("SOLANGE", WHILE, "SOLANGE ^\n\t\nENDE SOLANGE")); + KEYWORDS.Add(new PseudocodeType("WIEDERHOLE", DO, "WIEDERHOLE\n\t\nSOLANGE ^")); + KEYWORDS.Add(new PseudocodeType("FÜR", FOR, new List() + { + new PseudocodeAutocompleteItem("FÜR ^ BIS SCHRITT \n\t\nENDE FÜR", "FÜR-BIS Block"), + new PseudocodeAutocompleteItem("FÜR ^ IN \n\t\nENDE FÜR", "FÜR-IN Block") + })); + KEYWORDS.Add(new PseudocodeType("OPERATION", FUNCTION, "OPERATION ^()\n\t")); + KEYWORDS.Add(new PseudocodeType("Liste", TYPE_LIST, "Liste<^>")); + + // built-in methods + KEYWORDS.Add(new PseudocodeType("schreibe", IDENTIFIER, "schreibe(^)")); + KEYWORDS.Add(new PseudocodeType("warte", IDENTIFIER, "warte(^)")); + KEYWORDS.Add(new PseudocodeType("benutzereingabe", IDENTIFIER, "benutzereingabe<^>(\"\", \"\")")); + + // if/else + KEYWORDS.Add(new PseudocodeType("SONST", ELSE)); + KEYWORDS.Add(new PseudocodeType("ENDE WENN", END_IF)); + + + // switch/case + KEYWORDS.Add(new PseudocodeType("GLEICH", SWITCH_SUFFIX)); + KEYWORDS.Add(new PseudocodeType("ENDE FALLS", END_SWITCH)); + + // (do) while + KEYWORDS.Add(new PseudocodeType("ENDE SOLANGE", END_WHILE)); + + // for + KEYWORDS.Add(new PseudocodeType("BIS", FOR_TO)); + KEYWORDS.Add(new PseudocodeType("SCHRITT", FOR_STEP)); + KEYWORDS.Add(new PseudocodeType("IN", FOR_IN)); + KEYWORDS.Add(new PseudocodeType("ENDE FÜR", END_FOR)); + + // break + KEYWORDS.Add(new PseudocodeType("ABBRUCH", BREAK)); + + // function + KEYWORDS.Add(new PseudocodeType("RÜCKGABE", RETURN)); + + // booleans + KEYWORDS.Add(new PseudocodeType("wahr", TRUE)); + KEYWORDS.Add(new PseudocodeType("true", TRUE)); + KEYWORDS.Add(new PseudocodeType("falsch", FALSE)); + KEYWORDS.Add(new PseudocodeType("false", FALSE)); + + // compare operators + KEYWORDS.Add(new PseudocodeType("UND", AND)); + KEYWORDS.Add(new PseudocodeType("ODER", OR)); + + // boolean types + KEYWORDS.Add(new PseudocodeType("Boolean", TYPE_BOOL)); + KEYWORDS.Add(new PseudocodeType("boolean", TYPE_BOOL)); + KEYWORDS.Add(new PseudocodeType("bool", TYPE_BOOL)); + + // int types + KEYWORDS.Add(new PseudocodeType("GZ", TYPE_INT)); + KEYWORDS.Add(new PseudocodeType("Integer", TYPE_INT)); + KEYWORDS.Add(new PseudocodeType("int", TYPE_INT)); + + // double types + KEYWORDS.Add(new PseudocodeType("FKZ", TYPE_DOUBLE)); + KEYWORDS.Add(new PseudocodeType("Real", TYPE_DOUBLE)); + KEYWORDS.Add(new PseudocodeType("double", TYPE_DOUBLE)); + + // char types + KEYWORDS.Add(new PseudocodeType("Zeichen", TYPE_CHAR)); + KEYWORDS.Add(new PseudocodeType("char", TYPE_CHAR)); + + // string types + KEYWORDS.Add(new PseudocodeType("Text", TYPE_STRING)); + KEYWORDS.Add(new PseudocodeType("String", TYPE_STRING)); + KEYWORDS.Add(new PseudocodeType("string", TYPE_STRING)); + + // new keyword + KEYWORDS.Add(new PseudocodeType("NEU", NEW)); + + // null + KEYWORDS.Add(new PseudocodeType("NICHTS", NULL)); + } + } +} diff --git a/pseudocodeIde/interpreter/pseudocode/PseudocodeType.cs b/pseudocodeIde/interpreter/pseudocode/PseudocodeType.cs new file mode 100644 index 0000000..83e1445 --- /dev/null +++ b/pseudocodeIde/interpreter/pseudocode/PseudocodeType.cs @@ -0,0 +1,96 @@ +// Pseudocode IDE - Execute Pseudocode for the German (BW) 2024 Abitur +// Copyright (C) 2024 PocketMiner82 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +using System; +using System.Collections.Generic; + +namespace pseudocode_ide.interpreter.pseudocode +{ + /// + /// Represents a type of pseudocode with its keyword, token type, and autocomplete items. + /// + public class PseudocodeType + { + /// + /// The keyword associated with this pseudocode type. + /// + public readonly string Keyword; + + /// + /// The token type associated with this pseudocode type. + /// + public readonly TokenType TType; + + /// + /// A list of autocomplete items for this pseudocode type. + /// + public readonly List ACItems = new List(); + + /// + /// Initializes a new instance of the class with the specified keyword, token type, and snippets. + /// + /// The keyword for this pseudocode type. + /// The token type for this pseudocode type. + /// The snippets to be added as autocomplete items. + public PseudocodeType(string keyword, TokenType tType, params string[] snippets) + { + Keyword = keyword; + TType = tType; + + if (snippets != null) + { + foreach (string snippet in snippets) + { + ACItems.Add(new PseudocodeAutocompleteItem(snippet, $"{keyword} Block")); + } + } + + ACItems.Add(new PseudocodeAutocompleteItem(keyword)); + } + + /// + /// Initializes a new instance of the class with the specified keyword, token type, and autocomplete items. + /// + /// The keyword for this pseudocode type. + /// The token type for this pseudocode type. + /// The autocomplete items for this pseudocode type. + public PseudocodeType(string keyword, TokenType tType, List acItems) + { + Keyword = keyword; + TType = tType; + + if (acItems != null) + { + ACItems.AddRange(acItems); + } + + ACItems.Add(new PseudocodeAutocompleteItem(keyword)); + } + + /// + /// Implicitly converts a to a . + /// + /// The to convert. + public static implicit operator TokenType(PseudocodeType pseudocodeType) + { + return pseudocodeType == null ? throw new ArgumentNullException(nameof(pseudocodeType)) : pseudocodeType.TType; + } + + /// + /// Implicitly converts a to a list of . + /// + /// The to convert. + public static implicit operator List(PseudocodeType pseudocodeType) + { + return pseudocodeType == null ? throw new ArgumentNullException(nameof(pseudocodeType)) : pseudocodeType.ACItems; + } + } +} diff --git a/pseudocodeIde/interpreter/pseudocode/PseudocodeTypeDictionary.cs b/pseudocodeIde/interpreter/pseudocode/PseudocodeTypeDictionary.cs new file mode 100644 index 0000000..2c88042 --- /dev/null +++ b/pseudocodeIde/interpreter/pseudocode/PseudocodeTypeDictionary.cs @@ -0,0 +1,30 @@ +// Pseudocode IDE - Execute Pseudocode for the German (BW) 2024 Abitur +// Copyright (C) 2024 PocketMiner82 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +using System.Collections.Generic; + +namespace pseudocode_ide.interpreter.pseudocode +{ + /// + /// Represents a collection for storing and retrieving PseudocodeType objects by their Keyword. + /// + public class PseudocodeTypeDictionary : Dictionary + { + /// + /// Adds a PseudocodeType to the dictionary. + /// + /// The PseudocodeType to add. + public void Add(PseudocodeType pseudocodeType) + { + Add(pseudocodeType.Keyword, pseudocodeType); + } + } +} diff --git a/pseudocodeIde/interpreter/scanner/Token.cs b/pseudocodeIde/interpreter/pseudocode/Token.cs similarity index 97% rename from pseudocodeIde/interpreter/scanner/Token.cs rename to pseudocodeIde/interpreter/pseudocode/Token.cs index bbdcc1d..dba4367 100644 --- a/pseudocodeIde/interpreter/scanner/Token.cs +++ b/pseudocodeIde/interpreter/pseudocode/Token.cs @@ -9,7 +9,7 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY -namespace pseudocodeIde.interpreter +namespace pseudocode_ide.interpreter.pseudocode { public class Token { diff --git a/pseudocodeIde/interpreter/scanner/TokenType.cs b/pseudocodeIde/interpreter/pseudocode/TokenType.cs similarity index 96% rename from pseudocodeIde/interpreter/scanner/TokenType.cs rename to pseudocodeIde/interpreter/pseudocode/TokenType.cs index fc51ddf..f88f189 100644 --- a/pseudocodeIde/interpreter/scanner/TokenType.cs +++ b/pseudocodeIde/interpreter/pseudocode/TokenType.cs @@ -9,7 +9,7 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY -namespace pseudocodeIde.interpreter +namespace pseudocode_ide.interpreter.pseudocode { /// /// The type of a token that was lexed diff --git a/pseudocodeIde/interpreter/scanner/Scanner.cs b/pseudocodeIde/interpreter/scanner/Scanner.cs index 807762b..cdf8f7b 100644 --- a/pseudocodeIde/interpreter/scanner/Scanner.cs +++ b/pseudocodeIde/interpreter/scanner/Scanner.cs @@ -9,20 +9,17 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY +using pseudocode_ide.interpreter.pseudocode; using pseudocodeIde.interpreter.logging; using System; using System.Collections.Generic; -using static pseudocodeIde.interpreter.TokenType; +using static pseudocode_ide.interpreter.pseudocode.TokenType; +using static pseudocode_ide.interpreter.pseudocode.PseudocodeKeywords; namespace pseudocodeIde.interpreter { public class Scanner { - /// - /// All the defined keywords in pseudocode and their corresponding token. - /// - public static readonly Dictionary KEYWORDS = new Dictionary(); - /// /// If '=' is used to compare values (e.g. 1=1 would be true) /// or if it is used to define variables (e.g. i:int = 1) @@ -54,71 +51,6 @@ public class Scanner /// private int _line = 1; - /// - /// Add the keywords contents to the readonly static list - /// - static Scanner() - { - KEYWORDS.Add("WENN", IF); - KEYWORDS.Add("SONST", ELSE); - KEYWORDS.Add("ENDE WENN", END_IF); - - KEYWORDS.Add("FALLS", SWITCH_PREFIX); - KEYWORDS.Add("GLEICH", SWITCH_SUFFIX); - KEYWORDS.Add("ENDE FALLS", END_SWITCH); - - KEYWORDS.Add("SOLANGE", WHILE); - KEYWORDS.Add("ENDE SOLANGE", END_WHILE); - KEYWORDS.Add("WIEDERHOLE", DO); - - KEYWORDS.Add("FÜR", FOR); - KEYWORDS.Add("BIS", FOR_TO); - KEYWORDS.Add("SCHRITT", FOR_STEP); - KEYWORDS.Add("IN", FOR_IN); - KEYWORDS.Add("ENDE FÜR", END_FOR); - - KEYWORDS.Add("ABBRUCH", BREAK); - - KEYWORDS.Add("OPERATION", FUNCTION); - KEYWORDS.Add("RÜCKGABE", RETURN); - - KEYWORDS.Add("wahr", TRUE); - KEYWORDS.Add("true", TRUE); - KEYWORDS.Add("falsch", FALSE); - KEYWORDS.Add("false", FALSE); - - KEYWORDS.Add("UND", AND); - KEYWORDS.Add("ODER", OR); - - KEYWORDS.Add("Boolean", TYPE_BOOL); - KEYWORDS.Add("boolean", TYPE_BOOL); - KEYWORDS.Add("bool", TYPE_BOOL); - - KEYWORDS.Add("GZ", TYPE_INT); - KEYWORDS.Add("Integer", TYPE_INT); - KEYWORDS.Add("int", TYPE_INT); - - KEYWORDS.Add("FKZ", TYPE_DOUBLE); - KEYWORDS.Add("Real", TYPE_DOUBLE); - KEYWORDS.Add("double", TYPE_DOUBLE); - - KEYWORDS.Add("Zeichen", TYPE_CHAR); - KEYWORDS.Add("char", TYPE_CHAR); - - KEYWORDS.Add("Text", TYPE_STRING); - KEYWORDS.Add("String", TYPE_STRING); - KEYWORDS.Add("string", TYPE_STRING); - - KEYWORDS.Add("Liste", TYPE_LIST); - KEYWORDS.Add("NEU", NEW); - - KEYWORDS.Add("NICHTS", NULL); - - KEYWORDS.Add("schreibe", IDENTIFIER); - KEYWORDS.Add("warte", IDENTIFIER); - KEYWORDS.Add("benutzereingabe", IDENTIFIER); - } - /// /// This class converts Pseudocode to Tokens /// diff --git a/pseudocodeIde/interpreter/scanner/SyntaxHighlightingLexer.cs b/pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs similarity index 98% rename from pseudocodeIde/interpreter/scanner/SyntaxHighlightingLexer.cs rename to pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs index 7024cfe..84cbb5b 100644 --- a/pseudocodeIde/interpreter/scanner/SyntaxHighlightingLexer.cs +++ b/pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs @@ -9,7 +9,7 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY -using pseudocodeIde.interpreter; +using pseudocode_ide.interpreter.pseudocode; using ScintillaNET; using System; using System.Diagnostics; @@ -17,7 +17,7 @@ namespace pseudocode_ide.interpreter.scanner { // mostly from https://github.com/jacobslusser/ScintillaNET/wiki/Custom-Syntax-Highlighting - public static class SyntaxHighlightingLexer + public static class SyntaxHighlightingScanner { // all possible text styles public const int STYLE_DEFAULT = 0; @@ -164,7 +164,7 @@ public static void Style(Scintilla scintilla, int startPos, int endPos) int style = STYLE_IDENTIFIER; // if the identifier is in the keyword list, then it will has a differnt color - if (Scanner.KEYWORDS.ContainsKey(identifier)) + if (PseudocodeKeywords.KEYWORDS.ContainsKey(identifier)) { style = STYLE_KEYWORD; } diff --git a/pseudocodeIde/pseudocodeIde.csproj b/pseudocodeIde/pseudocodeIde.csproj index 18534de..b07ee84 100644 --- a/pseudocodeIde/pseudocodeIde.csproj +++ b/pseudocodeIde/pseudocodeIde.csproj @@ -37,6 +37,7 @@ + @@ -117,6 +118,6 @@ - + \ No newline at end of file