From cc0b084c84361d69b3ba9d13b9af6db93219ad56 Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Sat, 31 May 2025 00:20:29 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=9A=E6=9C=AC=E8=8A=82=E7=82=B9=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AF=B9Char=E5=AD=97=E9=9D=A2=E9=87=8F=E7=9A=84?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Serein.Script/Node/CharNode.cs | 17 +++++ Serein.Script/Serein.Script.csproj | 3 + Serein.Script/SereinScriptInterpreter.cs | 2 + Serein.Script/SereinScriptLexer.cs | 37 ++++++++++- Serein.Script/SereinScriptParser.cs | 18 +++-- Workbench/App.xaml.cs | 73 ++------------------- Workbench/ServiceCollectionExtensions.cs | 83 ++++++++++++++++++++++++ Workbench/Views/MainMenuBarView.xaml | 2 +- 8 files changed, 159 insertions(+), 76 deletions(-) create mode 100644 Serein.Script/Node/CharNode.cs create mode 100644 Workbench/ServiceCollectionExtensions.cs diff --git a/Serein.Script/Node/CharNode.cs b/Serein.Script/Node/CharNode.cs new file mode 100644 index 0000000..d6fad31 --- /dev/null +++ b/Serein.Script/Node/CharNode.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.Script.Node +{ + internal class CharNode : ASTNode + { + public char Value { get; } + public CharNode(string value) + { + Value = char.Parse(value); + } + } +} diff --git a/Serein.Script/Serein.Script.csproj b/Serein.Script/Serein.Script.csproj index 783b61f..d44f15f 100644 --- a/Serein.Script/Serein.Script.csproj +++ b/Serein.Script/Serein.Script.csproj @@ -8,10 +8,13 @@ + + + diff --git a/Serein.Script/SereinScriptInterpreter.cs b/Serein.Script/SereinScriptInterpreter.cs index dfefd74..e3f5d57 100644 --- a/Serein.Script/SereinScriptInterpreter.cs +++ b/Serein.Script/SereinScriptInterpreter.cs @@ -442,6 +442,8 @@ namespace Serein.Script return numberNode.Value; // 返回数值 case StringNode stringNode: return stringNode.Value; // 返回字符串值 + case CharNode charNode: + return charNode.Value; // 返回Char case IdentifierNode identifierNode: return context.GetVarValue(identifierNode.Name); //throw new SereinSciptException(identifierNode, "尝试使用值为null的变量"); diff --git a/Serein.Script/SereinScriptLexer.cs b/Serein.Script/SereinScriptLexer.cs index 23bc11f..9172190 100644 --- a/Serein.Script/SereinScriptLexer.cs +++ b/Serein.Script/SereinScriptLexer.cs @@ -11,7 +11,7 @@ namespace Serein.Script /// Null, /// - /// 标识符 + /// 标识符(变量) /// Identifier, /// @@ -27,6 +27,10 @@ namespace Serein.Script /// String, /// + /// Char字符 + /// + Char, + /// /// 插值字符串 /// InterpolatedString, @@ -163,6 +167,20 @@ namespace Serein.Script return ReadString(); } + if (currentChar == '\'') + { + if (_input[_index + 2] == '\'') + { + + return ReadChar(); + } + else + { + throw new Exception($"not is char: {currentChar},in Line.{_row}."); + } + } + + // 跳过注释 if (_input[_index] == '/' && _input[_index + 1] == '/') { @@ -332,6 +350,23 @@ namespace Serein.Script //return new Token(TokenType.String, value.ToString()); } + /// + /// 读取硬编码的Char字符 + /// + /// + /// + private Token ReadChar() + { + _index++; // 跳过开头的引号 + var start = _index; + var cahrValue = _input.Slice(start, 1).ToString(); + _index++; // 跳过Char字符串后的引号 + return CreateToken(TokenType.Char, cahrValue); + + // _index++; // 跳过结束的引号 + //return new Token(TokenType.String, value.ToString()); + } + /// /// 获取对应行的代码文本 /// diff --git a/Serein.Script/SereinScriptParser.cs b/Serein.Script/SereinScriptParser.cs index 6827674..7f0d1ba 100644 --- a/Serein.Script/SereinScriptParser.cs +++ b/Serein.Script/SereinScriptParser.cs @@ -210,7 +210,7 @@ namespace Serein.Script private ASTNode ParseLetAssignment() { _currentToken = _lexer.NextToken(); // Consume "let" - string variable = _currentToken.Value.ToString(); + string variable = _currentToken.Value.ToString(); // 变量名称 _currentToken = _lexer.NextToken(); // Consume identifier ASTNode value; if (_currentToken.Type == TokenType.Semicolon) @@ -419,6 +419,7 @@ namespace Serein.Script _currentToken = _lexer.NextToken(); // consume "(" var arguments = new List(); + bool isBreak = false; while (_currentToken.Type != TokenType.ParenthesisRight) { var arg = Expression(); @@ -430,11 +431,12 @@ namespace Serein.Script } if (_currentToken.Type == TokenType.Semicolon) { + isBreak = true; break; // consume ";" } } - - _currentToken = _lexer.NextToken(); // consume ")" + if(!isBreak) + _currentToken = _lexer.NextToken(); // consume ")" //var node = Statements[^1]; @@ -586,8 +588,14 @@ namespace Serein.Script if (_currentToken.Type == TokenType.String) { var text = _currentToken.Value; - _currentToken = _lexer.NextToken(); // 消耗数字 - return new StringNode(text.ToString()).SetTokenInfo(_currentToken); + _currentToken = _lexer.NextToken(); // 消耗字符串 + return new StringNode(text).SetTokenInfo(_currentToken); + } + if (_currentToken.Type == TokenType.Char) + { + var text = _currentToken.Value; + _currentToken = _lexer.NextToken(); // 消耗Char + return new CharNode(text).SetTokenInfo(_currentToken); } if( _currentToken.Type == TokenType.InterpolatedString) { diff --git a/Workbench/App.xaml.cs b/Workbench/App.xaml.cs index 7e3d60d..f044daa 100644 --- a/Workbench/App.xaml.cs +++ b/Workbench/App.xaml.cs @@ -16,72 +16,7 @@ using System.Windows.Threading; namespace Serein.Workbench { - public static class ServiceCollectionExtensions - { - /// - /// 注册ViewModel - /// - /// - public static void AddViewModelServices(this IServiceCollection collection) - { - collection.AddSingleton(); // 主窗体 - - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - - collection.AddTransient(); // 画布 - collection.AddTransient(); // 画布节点树视图 - } - - public static void AddWorkbenchServices(this IServiceCollection collection) - { - collection.AddSingleton(); // 流程事件管理 - collection.AddSingleton();// 按键事件管理 - collection.AddSingleton(); // 流程事件管理 - collection.AddSingleton(); // 项目管理 - collection.AddSingleton(); // 节点操作管理 - } - - - /// - /// 注册流程接口相关实例 - /// - /// - public static void AddFlowServices(this IServiceCollection collection) - { - #region 创建实例 - Func getSyncContext = null; - Dispatcher.CurrentDispatcher.Invoke(() => - { - var uiContext = SynchronizationContext.Current; // 在UI线程上获取UI线程上下文信息 - if (uiContext is not null) - { - getSyncContext = () => uiContext; - } - - }); - - UIContextOperation? uIContextOperation = null; - uIContextOperation = new UIContextOperation(getSyncContext); // 封装一个调用UI线程的工具类 - var flowEnvironmentDecorator = new FlowEnvironmentDecorator(); - flowEnvironmentDecorator.SetUIContextOperation(uIContextOperation); - collection.AddSingleton(uIContextOperation); // 注册UI线程操作上下文 - collection.AddSingleton(flowEnvironmentDecorator); // 注册运行环境 - collection.AddSingleton(flowEnvironmentDecorator); // 注册运行环境事件 - - #endregion - - } - } - - - + /// /// Interaction logic for App.xaml /// @@ -117,10 +52,10 @@ namespace Serein.Workbench // 这里是测试代码,可以删除 private async Task LoadLocalProjectAsync() { - var projectService = App.GetService(); - await Task.Delay(500); - if (1 == 1) + if (1 == 11) { + var projectService = App.GetService(); + await Task.Delay(500); string filePath; filePath = @"F:\TempFile\flow\temp2\project.dnf"; projectService.LoadLocalProject(filePath); diff --git a/Workbench/ServiceCollectionExtensions.cs b/Workbench/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..d5bb639 --- /dev/null +++ b/Workbench/ServiceCollectionExtensions.cs @@ -0,0 +1,83 @@ +using Microsoft.Extensions.DependencyInjection; +using Serein.Library.Api; +using Serein.Library.Utils; +using Serein.NodeFlow.Env; +using Serein.Workbench.Api; +using Serein.Workbench.Services; +using Serein.Workbench.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Threading; + +namespace Serein.Workbench +{ + public static class ServiceCollectionExtensions + { + /// + /// 注册ViewModel + /// + /// + public static void AddViewModelServices(this IServiceCollection collection) + { + collection.AddSingleton(); // 主窗体 + + collection.AddSingleton(); + collection.AddSingleton(); + collection.AddSingleton(); + collection.AddSingleton(); + collection.AddSingleton(); + collection.AddSingleton(); + collection.AddSingleton(); + collection.AddSingleton(); + + collection.AddTransient(); // 画布 + collection.AddTransient(); // 画布节点树视图 + } + + public static void AddWorkbenchServices(this IServiceCollection collection) + { + collection.AddSingleton(); // 流程事件管理 + collection.AddSingleton();// 按键事件管理 + collection.AddSingleton(); // 流程事件管理 + collection.AddSingleton(); // 项目管理 + collection.AddSingleton(); // 节点操作管理 + } + + + /// + /// 注册流程接口相关实例 + /// + /// + public static void AddFlowServices(this IServiceCollection collection) + { + #region 创建实例 + Func getSyncContext = null; + Dispatcher.CurrentDispatcher.Invoke(() => + { + var uiContext = SynchronizationContext.Current; // 在UI线程上获取UI线程上下文信息 + if (uiContext is not null) + { + getSyncContext = () => uiContext; + } + + }); + + UIContextOperation? uIContextOperation = null; + uIContextOperation = new UIContextOperation(getSyncContext); // 封装一个调用UI线程的工具类 + var flowEnvironmentDecorator = new FlowEnvironmentDecorator(); + flowEnvironmentDecorator.SetUIContextOperation(uIContextOperation); + collection.AddSingleton(uIContextOperation); // 注册UI线程操作上下文 + collection.AddSingleton(flowEnvironmentDecorator); // 注册运行环境 + collection.AddSingleton(flowEnvironmentDecorator); // 注册运行环境事件 + + #endregion + + } + } + + + +} diff --git a/Workbench/Views/MainMenuBarView.xaml b/Workbench/Views/MainMenuBarView.xaml index 7a1ffb4..c941476 100644 --- a/Workbench/Views/MainMenuBarView.xaml +++ b/Workbench/Views/MainMenuBarView.xaml @@ -13,7 +13,7 @@ - +