-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added CodeEditor and syntax highlighting
- Loading branch information
Walper
committed
Nov 22, 2023
1 parent
c72b0b3
commit 71d236f
Showing
13 changed files
with
435 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System; | ||
using AvaloniaEdit.Document; | ||
using AvaloniaEdit.Rendering; | ||
using LanguageParser.Parser; | ||
using SimpleExecutor.ViewModels; | ||
|
||
namespace SimpleExecutor.Models; | ||
|
||
public sealed class ExpressionSyntaxColorizer : DocumentColorizingTransformer | ||
{ | ||
private readonly MainViewModel _viewModel; | ||
|
||
public ExpressionSyntaxColorizer(MainViewModel viewModel) | ||
{ | ||
_viewModel = viewModel; | ||
} | ||
|
||
protected override void ColorizeLine(DocumentLine line) | ||
{ | ||
try | ||
{ | ||
var result = ExpressionsParser.Parse(_viewModel.Code); | ||
|
||
if (result.IsError) | ||
return; | ||
|
||
ExpressionsColorizer.Colorize(ChangeLinePart, line, result.Value); | ||
} | ||
catch (Exception e) | ||
Check warning on line 29 in SimpleExecutor/Models/ExpressionSyntaxColorizer.cs GitHub Actions / build
|
||
{ | ||
// ignored | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
using System; | ||
using Avalonia.Media; | ||
using AvaloniaEdit.Document; | ||
using AvaloniaEdit.Rendering; | ||
using LanguageParser.Common; | ||
using LanguageParser.Expressions; | ||
using LanguageParser.Lexer; | ||
using LanguageParser.Visitors; | ||
using static SimpleExecutor.Models.SyntaxColors; | ||
|
||
namespace SimpleExecutor.Models; | ||
|
||
public sealed class ExpressionsColorizer : ExpressionVisitor | ||
{ | ||
private readonly Action<int, int, Action<VisualLineElement>> _changeLinePart; | ||
private readonly DocumentLine _line; | ||
|
||
private ExpressionsColorizer(Action<int, int, Action<VisualLineElement>> changeLinePart, DocumentLine line) | ||
{ | ||
_changeLinePart = changeLinePart; | ||
_line = line; | ||
} | ||
|
||
public static void Colorize(Action<int, int, Action<VisualLineElement>> changeLinePart, DocumentLine line, | ||
ExpressionBase expression) | ||
{ | ||
var colorizer = new ExpressionsColorizer(changeLinePart, line); | ||
colorizer.Visit(expression); | ||
|
||
foreach (var trivia in expression.TrailingTrivia) | ||
colorizer.VisitTrivia(trivia); | ||
} | ||
|
||
public override void VisitTrivia(Token trivia) | ||
{ | ||
if (trivia.IsComment) | ||
SetForeground(trivia, CommentBrush); | ||
} | ||
|
||
public override void VisitBinary(BinaryExpression expression) | ||
{ | ||
Visit(expression.Left); | ||
SetForeground(expression.Operator.Token, OperatorBrush); | ||
Visit(expression.Right); | ||
} | ||
|
||
public override void VisitConstant(ConstantExpression expression) | ||
{ | ||
SetForeground(expression.Token, GetTokenBrush(expression.Token)); | ||
} | ||
|
||
public override void VisitFor(ForExpression expression) | ||
{ | ||
SetForeground(expression.ForToken, KeywordBrush); | ||
if (expression.Initialization is not null) | ||
Visit(expression.Initialization); | ||
|
||
if (expression.Condition is not null) | ||
Visit(expression.Condition); | ||
|
||
if (expression.Step is not null) | ||
Visit(expression.Step); | ||
|
||
Visit(expression.Body); | ||
} | ||
|
||
public override void VisitIf(IfExpression expression) | ||
{ | ||
SetForeground(expression.IfToken, KeywordBrush); | ||
Visit(expression.Condition); | ||
|
||
Visit(expression.ThenBranch); | ||
|
||
if (expression.ElseToken is not null) | ||
SetForeground(expression.ElseToken, KeywordBrush); | ||
|
||
if (expression.ElseBranch is not null) | ||
Visit(expression.ElseBranch); | ||
} | ||
|
||
public override void VisitInvocation(InvocationExpression expression) | ||
{ | ||
if (expression.Function is ConstantExpression constant) | ||
SetForeground(constant.Token, FunctionBrush); | ||
else | ||
Visit(expression.Function); | ||
|
||
foreach (var argument in expression.Arguments) | ||
Visit(argument); | ||
} | ||
|
||
public override void VisitParenthesized(ParenthesizedExpression expression) | ||
{ | ||
Visit(expression.Expression); | ||
} | ||
|
||
public override void VisitRepeat(RepeatExpression expression) | ||
{ | ||
SetForeground(expression.RepeatToken, KeywordBrush); | ||
|
||
Visit(expression.Body); | ||
|
||
SetForeground(expression.UntilToken, KeywordBrush); | ||
|
||
Visit(expression.Condition); | ||
} | ||
|
||
public override void VisitScope(ScopeExpression expression) | ||
{ | ||
foreach (var innerExpression in expression.InnerExpressions) | ||
Visit(innerExpression); | ||
} | ||
|
||
public override void VisitVariable(VariableExpression expression) | ||
{ | ||
SetForeground(expression.TypeToken, KeywordBrush); | ||
|
||
SetForeground(expression.NameToken, GetTokenBrush(expression.NameToken)); | ||
|
||
if (expression.AssignmentExpression is not null) | ||
Visit(expression.AssignmentExpression); | ||
} | ||
|
||
public override void VisitWhile(WhileExpression expression) | ||
{ | ||
SetForeground(expression.WhileToken, KeywordBrush); | ||
|
||
Visit(expression.Condition); | ||
Visit(expression.Body); | ||
} | ||
|
||
private void WalkLeadingTrivia(Token token) | ||
{ | ||
foreach (var trivia in token.LeadingTrivia) | ||
VisitTrivia(trivia); | ||
} | ||
|
||
private void SetForeground(StringRange range, IBrush brush) | ||
{ | ||
if (new StringRange(_line.Offset, _line.Length).Intersection(range) is { } intersection) | ||
_changeLinePart.Invoke(intersection.Start, intersection.End, | ||
e => e.TextRunProperties.SetForegroundBrush(brush)); | ||
} | ||
|
||
private void SetForeground(Token token, IImmutableBrush brush) | ||
{ | ||
WalkLeadingTrivia(token); | ||
SetForeground(token.Range, brush); | ||
} | ||
|
||
private static IImmutableBrush GetTokenBrush(Token token) | ||
{ | ||
if (token.IsNumber) | ||
return NumberBrush; | ||
|
||
if (token.IsKeyWord) | ||
return KeywordBrush; | ||
|
||
if (token.IsString) | ||
return StringBrush; | ||
|
||
return ForegroundBrush; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using Avalonia.Media; | ||
|
||
namespace SimpleExecutor.Models; | ||
|
||
public static class SyntaxColors | ||
{ | ||
public static readonly IImmutableBrush FunctionBrush = | ||
new SolidColorBrush(Color.FromRgb(21, 139, 134)).ToImmutable(); | ||
|
||
public static readonly IImmutableBrush KeywordBrush = new SolidColorBrush(Color.FromRgb(80, 125, 233)).ToImmutable(); | ||
|
||
public static readonly IImmutableBrush StringBrush = | ||
new SolidColorBrush(Color.FromRgb(196, 158, 107)).ToImmutable(); | ||
|
||
public static readonly IImmutableBrush NumberBrush = | ||
new SolidColorBrush(Color.FromRgb(237, 148, 192)).ToImmutable(); | ||
|
||
public static readonly IImmutableBrush OperatorBrush = | ||
new SolidColorBrush(Color.FromRgb(50,50,50)).ToImmutable(); | ||
|
||
public static readonly IImmutableBrush CommentBrush = | ||
new SolidColorBrush(Color.FromRgb(81, 115, 66)).ToImmutable(); | ||
|
||
public static readonly IImmutableBrush ForegroundBrush = | ||
new SolidColorBrush(Color.FromRgb(50,50,50)).ToImmutable(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using System; | ||
using System.Linq; | ||
using Avalonia.Media; | ||
using AvaloniaEdit.Document; | ||
using AvaloniaEdit.Rendering; | ||
using LanguageParser.Common; | ||
using LanguageParser.Interfaces; | ||
using LanguageParser.Lexer; | ||
using static SimpleExecutor.Models.SyntaxColors; | ||
using Tokenizer = LanguageParser.Lexer.Tokenizer; | ||
|
||
namespace SimpleExecutor.Models; | ||
|
||
public sealed class TokensColorizer | ||
{ | ||
private readonly Action<int, int, Action<VisualLineElement>> _changeLinePart; | ||
private readonly DocumentLine _line; | ||
private readonly IStream<Token> _tokenStream; | ||
|
||
public TokensColorizer(IStream<Token> tokenStream, Action<int, int, Action<VisualLineElement>> changeLinePart, | ||
DocumentLine line) | ||
{ | ||
_tokenStream = tokenStream; | ||
_changeLinePart = changeLinePart; | ||
_line = line; | ||
} | ||
|
||
public static void Colorize(string code, Action<int, int, Action<VisualLineElement>> changeLinePart, DocumentLine line) | ||
{ | ||
var tokens = Tokenizer.Tokenize(code); | ||
|
||
new TokensColorizer(tokens, changeLinePart, line).Colorize(); | ||
} | ||
|
||
private void Colorize() | ||
{ | ||
IImmutableBrush? brush; | ||
while (_tokenStream.CanAdvance) | ||
{ | ||
WalkLeadingTrivia(_tokenStream.Current); | ||
brush = GetTokenBrush(_tokenStream.Current); | ||
if (brush is not null) | ||
SetForeground(_tokenStream.Current, brush); | ||
_tokenStream.Advance(); | ||
} | ||
|
||
WalkLeadingTrivia(_tokenStream.Current); | ||
brush = GetTokenBrush(_tokenStream.Current); | ||
if (brush is not null) | ||
SetForeground(_tokenStream.Current, brush); | ||
} | ||
|
||
private void WalkLeadingTrivia(Token token) | ||
{ | ||
foreach (var trivia in token.LeadingTrivia.Where(trivia => trivia.IsComment)) | ||
SetForeground(trivia, CommentBrush); | ||
} | ||
|
||
private void SetForeground(StringRange range, IBrush brush) | ||
{ | ||
if (new StringRange(_line.Offset, _line.Length).Intersection(range) is { } intersection) | ||
_changeLinePart.Invoke(intersection.Start, intersection.End, | ||
e => e.TextRunProperties.SetForegroundBrush(brush)); | ||
} | ||
|
||
private void SetForeground(Token token, IImmutableBrush brush) | ||
{ | ||
WalkLeadingTrivia(token); | ||
var tokenRange = token.Range; | ||
|
||
if (token.IsString) | ||
tokenRange = new StringRange(tokenRange.Start - 1, tokenRange.Length + 2); | ||
|
||
SetForeground(tokenRange, brush); | ||
} | ||
|
||
private static IImmutableBrush? GetTokenBrush(Token token) | ||
{ | ||
if (token.IsNumber) | ||
return NumberBrush; | ||
|
||
if (token.IsKeyWord) | ||
return KeywordBrush; | ||
|
||
if (token.IsString) | ||
return StringBrush; | ||
|
||
if (token.IsComment) | ||
return CommentBrush; | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using AvaloniaEdit.Document; | ||
using AvaloniaEdit.Rendering; | ||
using SimpleExecutor.ViewModels; | ||
|
||
namespace SimpleExecutor.Models; | ||
|
||
public sealed class TokensSyntaxColorizer : DocumentColorizingTransformer | ||
{ | ||
private readonly MainViewModel _viewModel; | ||
|
||
public TokensSyntaxColorizer(MainViewModel viewModel) | ||
{ | ||
_viewModel = viewModel; | ||
} | ||
|
||
protected override void ColorizeLine(DocumentLine line) | ||
{ | ||
try | ||
{ | ||
TokensColorizer.Colorize(_viewModel.Code, ChangeLinePart, line); | ||
} | ||
catch (Exception) | ||
{ | ||
// ignored | ||
} | ||
} | ||
} |
Oops, something went wrong.