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 @@