From e253fc562d8d6c59c97de66be2c6fbe600babe17 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 3 Dec 2023 12:56:54 +0000 Subject: [PATCH] syntact highlighting --- .vscode/launch.json | 2 +- irules.core/Clause.cs | 7 +- irules.core/ClauseChecker.cs | 9 +- samples/data.red | 1 + samples/red/App.axaml.cs | 2 +- samples/red/IronyGrammarTransformer.cs | 13 +++ samples/red/MainWindow.axaml | 10 +- samples/red/MainWindow.axaml.cs | 126 +++++++++++++++++++++++-- samples/red/red.csproj | 3 +- 9 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 samples/data.red create mode 100644 samples/red/IronyGrammarTransformer.cs diff --git a/.vscode/launch.json b/.vscode/launch.json index 86e5341..8b563a7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": ".NET Core Launch (console)", + "name": ".NET Core Launch red sample", "type": "coreclr", "request": "launch", "preLaunchTask": "build", diff --git a/irules.core/Clause.cs b/irules.core/Clause.cs index 55437e9..6045299 100644 --- a/irules.core/Clause.cs +++ b/irules.core/Clause.cs @@ -4,6 +4,7 @@ using System.Data; using System.Drawing; using System.Linq; using System.Text; +using Irony.Ast; using Irony.Interpreter.Ast; using Irony.Parsing; @@ -12,6 +13,8 @@ namespace irules.core [Language("IRule", "0.1", "Clauses grammar.")] public class ClauseGrammar : Grammar { + private readonly IdOptions idoptions; + public ClauseGrammar() { var comment = new CommentTerminal("comment", "#", "\n"); @@ -23,11 +26,12 @@ namespace irules.core NonTerminal idOrRelation = new NonTerminal("idOrRelation"); NonTerminal SOrOr = new NonTerminal("SOrOr"); IdentifierTerminal id = new IdentifierTerminal("Id"); + var orExpr = new NonTerminal("OrExpr", typeof(BinaryOperationNode)); var andExpr = new NonTerminal("AndExpr", typeof(BinaryOperationNode)); var neg = new NonTerminal("Negation", typeof(UnaryOperationNode)) { - Rule = "^" + andExpr + ReduceHere() + Rule = "^" + singleByOr + ReduceHere() }; expr.Rule = "(" + expr + ")" | SOrOr ; SOrOr.Rule = orExpr | singleByOr; @@ -40,6 +44,7 @@ namespace irules.core RegisterBracePair("(", ")"); RegisterOperators(30, "&|^"); Root = expr; + } } } diff --git a/irules.core/ClauseChecker.cs b/irules.core/ClauseChecker.cs index 224cd00..ade7541 100644 --- a/irules.core/ClauseChecker.cs +++ b/irules.core/ClauseChecker.cs @@ -1,3 +1,4 @@ +using System.Runtime.InteropServices; using Irony.Interpreter; using Irony.Parsing; @@ -5,6 +6,10 @@ namespace irules.core { public class ClauseChecker { + public TokenList LastScriptTokens => app.LastScript?.Tokens; + + public ParseTree LatestParsedTree { get; private set; } + ScriptApp app; public ClauseChecker() { @@ -14,9 +19,11 @@ namespace irules.core app = new ScriptApp(r); } + + public virtual AppStatus Parse(string problem) { - app.Evaluate(problem); + LatestParsedTree = app.Parser.Parse(problem); try { switch (app.Status) { diff --git a/samples/data.red b/samples/data.red new file mode 100644 index 0000000..d834caa --- /dev/null +++ b/samples/data.red @@ -0,0 +1 @@ +Q&A \ No newline at end of file diff --git a/samples/red/App.axaml.cs b/samples/red/App.axaml.cs index 227b0f9..4bb734a 100644 --- a/samples/red/App.axaml.cs +++ b/samples/red/App.axaml.cs @@ -27,7 +27,7 @@ public partial class App : Application { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - desktop.MainWindow = new MainWindow(); + desktop.MainWindow = new MainWindow(checker); } base.OnFrameworkInitializationCompleted(); diff --git a/samples/red/IronyGrammarTransformer.cs b/samples/red/IronyGrammarTransformer.cs new file mode 100644 index 0000000..40f7f37 --- /dev/null +++ b/samples/red/IronyGrammarTransformer.cs @@ -0,0 +1,13 @@ +using AvaloniaEdit.Document; +using AvaloniaEdit.Rendering; + +namespace red +{ + internal class IronyGrammarTransformer : DocumentColorizingTransformer + { + protected override void ColorizeLine(DocumentLine line) + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/samples/red/MainWindow.axaml b/samples/red/MainWindow.axaml index c8cb4e7..3facea3 100644 --- a/samples/red/MainWindow.axaml +++ b/samples/red/MainWindow.axaml @@ -11,15 +11,17 @@ - + + + - - + + - + diff --git a/samples/red/MainWindow.axaml.cs b/samples/red/MainWindow.axaml.cs index c6be5ce..eeaf6ef 100644 --- a/samples/red/MainWindow.axaml.cs +++ b/samples/red/MainWindow.axaml.cs @@ -1,32 +1,128 @@ +using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; +using System.Linq; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Platform.Storage; +using Avalonia.Rendering; +using Avalonia.Threading; +using Avalonia.VisualTree; +using AvaloniaEdit; +using AvaloniaEdit.Highlighting; +using AvaloniaEdit.Rendering; +using Irony.Interpreter; +using Irony.Parsing; +using irules.core; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Avalonia.Media; namespace red; public partial class MainWindow : Window { - public MainWindow() + ClauseChecker checker; + public MainWindow(ClauseChecker checker) { + this.checker = checker; InitializeComponent(); + SetupTheme(); src.Text = "Hello !"; + src.TextChanged += OnTextChanged; + src.TextArea.TextView.VisualLinesChanged += TextView_VisualLinesChanged; + } + + private void TextView_VisualLinesChanged(object sender, EventArgs e) + { + //throw new NotImplementedException(); + } + + private void SetupTheme() + { + HighlightingColor keywork = new HighlightingColor + { Foreground = new SimpleHighlightingBrush(Color.FromRgb(255,155,50)) }; + + HighlightingColor comment = new HighlightingColor + { FontStyle = Avalonia.Media.FontStyle.Italic, + Foreground = new SimpleHighlightingBrush(Color.FromRgb(150,150,150)) }; + HighlightingColor identifier = new HighlightingColor + { Foreground = new SimpleHighlightingBrush(Color.FromRgb(255,195,255)) }; + + ColorTheme = new Dictionary + { + { TokenColor.Text, keywork}, + { TokenColor.Keyword, keywork}, + { TokenColor.Comment, comment}, + { TokenColor.Identifier, identifier}, + { TokenColor.String, comment}, + { TokenColor.Number, identifier} + }; + + + } + + Dictionary ColorTheme; + + + + private void OnTextChanged(object sender, EventArgs e) + { + var appstatus = checker.Parse(src.Text); + statusMessage.Text = "Parsing :" + + appstatus.ToString(); + switch (appstatus) + { + case AppStatus.Ready: + case AppStatus.SyntaxError: + case AppStatus.WaitingMoreInput: + src.TextArea.TextView.LineTransformers.Clear(); + RichTextModel model = new RichTextModel(); + + + checker.LatestParsedTree.Tokens?.ForEach ( + token => + { + switch(token.Category) + { + case TokenCategory.Error: + case TokenCategory.Directive: + case TokenCategory.Content: + case TokenCategory.Comment: + // token.Location.Line + model.ApplyHighlighting(token.Location.Position, token.Length, + ColorTheme[token.EditorInfo.Color]); + break; + + } + }); + transformer = new RichTextColorizer(model); + src.TextArea.TextView.LineTransformers.Add(transformer); + break; + } + + } + public void OnExit(object sender, RoutedEventArgs e) { Close(); } + string sourceFileName=null; + private ITextRunConstructionContext context; + private RichTextColorizer transformer; + private ITextRunConstructionContext transformerContext; + public void OnOpen(object sender, RoutedEventArgs e) { Task.Run(async () => { FilePickerOpenOptions options = new FilePickerOpenOptions { - AllowMultiple = true, - Title = "Red" + AllowMultiple = false, + Title = "Open a red file" }; options.FileTypeFilter = new FilePickerFileType[] { new("red"){ Patterns = new string[] { "*.red" } } }; @@ -35,11 +131,27 @@ public partial class MainWindow : Window if (result != null) { - foreach (var item in result) - { - System.Diagnostics.Debug.WriteLine($"Opened: {item.Path}"); - } + var item = result.First(); + sourceFileName = + item.Path.AbsolutePath; + Dispatcher.UIThread.Post(() => src.Text = File.ReadAllText(sourceFileName)); + System.Diagnostics.Debug.WriteLine($"Opened: {sourceFileName}"); } }); } + + public void OnSave(object sender, RoutedEventArgs e) + { + if (sourceFileName==null) OnSaveTo(sender, e); + File.WriteAllText(sourceFileName, src.Text); + } + public void OnSaveTo(object sender, RoutedEventArgs e) + { + throw new NotImplementedException(); + } + + public void OnRun(object sender, RoutedEventArgs e) + { + + } } \ No newline at end of file diff --git a/samples/red/red.csproj b/samples/red/red.csproj index 3cd0787..f272cf4 100644 --- a/samples/red/red.csproj +++ b/samples/red/red.csproj @@ -21,6 +21,7 @@ + @@ -29,7 +30,7 @@ - +