From b5e2f4cc160781c43069d8abb36f067b2a474ddd Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Mon, 13 Oct 2025 19:43:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=86=E5=A4=87=E5=B0=86RScript=E4=BD=9C?= =?UTF-8?q?=E4=B8=BA=E7=8B=AC=E7=AB=8B=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Convention/[RScript]/Matcher/BackMatcher.cs | 20 - Convention/[RScript]/Matcher/BreakMatcher.cs | 20 - .../Matcher/DefineVariableMatcher.cs | 20 - Convention/[RScript]/Matcher/GotoMatcher.cs | 22 -- Convention/[RScript]/Matcher/LabelMatcher.cs | 20 - .../[RScript]/Matcher/NamespaceMater.cs | 20 - .../[RScript]/Parser/ExpressionParser.cs | 76 ---- .../[RScript]/PublicTypes/RScriptException.cs | 11 - .../PublicTypes/RScriptImportClass.cs | 138 ------- .../[RScript]/PublicTypes/RScriptVariables.cs | 151 ------- Convention/[RScript]/RScriptContext.cs | 368 ------------------ Convention/[RScript]/RScriptEngine.cs | 111 ------ 12 files changed, 977 deletions(-) delete mode 100644 Convention/[RScript]/Matcher/BackMatcher.cs delete mode 100644 Convention/[RScript]/Matcher/BreakMatcher.cs delete mode 100644 Convention/[RScript]/Matcher/DefineVariableMatcher.cs delete mode 100644 Convention/[RScript]/Matcher/GotoMatcher.cs delete mode 100644 Convention/[RScript]/Matcher/LabelMatcher.cs delete mode 100644 Convention/[RScript]/Matcher/NamespaceMater.cs delete mode 100644 Convention/[RScript]/Parser/ExpressionParser.cs delete mode 100644 Convention/[RScript]/PublicTypes/RScriptException.cs delete mode 100644 Convention/[RScript]/PublicTypes/RScriptImportClass.cs delete mode 100644 Convention/[RScript]/PublicTypes/RScriptVariables.cs delete mode 100644 Convention/[RScript]/RScriptContext.cs delete mode 100644 Convention/[RScript]/RScriptEngine.cs diff --git a/Convention/[RScript]/Matcher/BackMatcher.cs b/Convention/[RScript]/Matcher/BackMatcher.cs deleted file mode 100644 index 95e5793..0000000 --- a/Convention/[RScript]/Matcher/BackMatcher.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Convention.RScript.Matcher -{ - public class BackMatcher : IRSentenceMatcher - { - public bool Match(string expression, ref RScriptSentence sentence) - { - Regex LabelRegex = new(@"back\s*\(\s*(.+)\s*\)"); - var LabelMatch = LabelRegex.Match(expression); - if (LabelMatch.Success) - { - sentence.mode = RScriptSentence.Mode.Backpoint; - sentence.content = LabelMatch.Groups[1].Value; - return true; - } - return false; - } - } -} diff --git a/Convention/[RScript]/Matcher/BreakMatcher.cs b/Convention/[RScript]/Matcher/BreakMatcher.cs deleted file mode 100644 index 7549d24..0000000 --- a/Convention/[RScript]/Matcher/BreakMatcher.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Convention.RScript.Matcher -{ - public class BreakMatcher : IRSentenceMatcher - { - public bool Match(string expression, ref RScriptSentence sentence) - { - Regex LabelRegex = new(@"break\s*\(\s*(.+)\s*\)"); - var LabelMatch = LabelRegex.Match(expression); - if (LabelMatch.Success) - { - sentence.mode = RScriptSentence.Mode.Breakpoint; - sentence.content = LabelMatch.Groups[1].Value; - return true; - } - return false; - } - } -} diff --git a/Convention/[RScript]/Matcher/DefineVariableMatcher.cs b/Convention/[RScript]/Matcher/DefineVariableMatcher.cs deleted file mode 100644 index f3d9018..0000000 --- a/Convention/[RScript]/Matcher/DefineVariableMatcher.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Convention.RScript.Matcher -{ - public class DefineVariableMatcher : IRSentenceMatcher - { - public bool Match(string expression, ref RScriptSentence sentence) - { - Regex DefineVariableRegex = new(@"(string|int|double|float|bool|var)\s+([a-zA-Z_][a-zA-Z0-9_]*)"); - var DefineVariableMatch = DefineVariableRegex.Match(expression); - if (DefineVariableMatch.Success) - { - sentence.mode = RScriptSentence.Mode.DefineVariable; - sentence.info = new() { DefineVariableMatch.Groups[1].Value, DefineVariableMatch.Groups[2].Value }; - return true; - } - return false; - } - } -} diff --git a/Convention/[RScript]/Matcher/GotoMatcher.cs b/Convention/[RScript]/Matcher/GotoMatcher.cs deleted file mode 100644 index 93e2ffe..0000000 --- a/Convention/[RScript]/Matcher/GotoMatcher.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Convention.RScript.Matcher -{ - public class GotoMatcher : IRSentenceMatcher - { - public bool Match(string expression, ref RScriptSentence sentence) - { - - Regex GotoRegex = new(@"goto\s*\(\s*(.+)\s*,\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)"); - var GotoMatch = GotoRegex.Match(expression); - if (GotoMatch.Success) - { - sentence.mode = RScriptSentence.Mode.Goto; - sentence.content = GotoMatch.Groups[2].Value; - sentence.info = new() { GotoMatch.Groups[1].Value, GotoMatch.Groups[2].Value }; - return true; - } - return false; - } - } -} diff --git a/Convention/[RScript]/Matcher/LabelMatcher.cs b/Convention/[RScript]/Matcher/LabelMatcher.cs deleted file mode 100644 index 2b7d622..0000000 --- a/Convention/[RScript]/Matcher/LabelMatcher.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Convention.RScript.Matcher -{ - public class LabelMatcher : IRSentenceMatcher - { - public bool Match(string expression, ref RScriptSentence sentence) - { - Regex LabelRegex = new(@"label\s*\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)"); - var LabelMatch = LabelRegex.Match(expression); - if (LabelMatch.Success) - { - sentence.mode = RScriptSentence.Mode.Label; - sentence.content = LabelMatch.Groups[1].Value; - return true; - } - return false; - } - } -} diff --git a/Convention/[RScript]/Matcher/NamespaceMater.cs b/Convention/[RScript]/Matcher/NamespaceMater.cs deleted file mode 100644 index 0059bed..0000000 --- a/Convention/[RScript]/Matcher/NamespaceMater.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Convention.RScript.Matcher -{ - public class NamespaceMater : IRSentenceMatcher - { - public bool Match(string expression, ref RScriptSentence sentence) - { - if (expression == "{") - { - sentence.mode = RScriptSentence.Mode.EnterNamespace; - return true; - } - else if (expression == "}") - { - sentence.mode = RScriptSentence.Mode.ExitNamespace; - return true; - } - return false; - } - } -} diff --git a/Convention/[RScript]/Parser/ExpressionParser.cs b/Convention/[RScript]/Parser/ExpressionParser.cs deleted file mode 100644 index 937bc95..0000000 --- a/Convention/[RScript]/Parser/ExpressionParser.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Flee.PublicTypes; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Convention.RScript.Parser -{ - public static class ExpressionExtension - { - public const double DefaultDoubleAccuracy = 1e-7; - - public static bool IsClose(this double value1, double value2, double maximumAbsoluteError = DefaultDoubleAccuracy) - { - if (double.IsInfinity(value1) || double.IsInfinity(value2)) - { - return Equals(value1, value2); - } - - if (double.IsNaN(value1) || double.IsNaN(value2)) - { - return false; - } - - var delta = value1 - value2; - return !(delta > maximumAbsoluteError || delta < -maximumAbsoluteError); - } - - public static bool IsCloseToZero(this double value, double maximumAbsoluteError = DefaultDoubleAccuracy) - { - return !(double.IsInfinity(value) || double.IsNaN(value) || value > maximumAbsoluteError || value < -maximumAbsoluteError); - } - } - - public class ExpressionParser - { - public readonly ExpressionContext context; - - public ExpressionParser(ExpressionContext context) - { - this.context = context; - } - - private readonly Dictionary CompileGenericExpression = new(); - private readonly Dictionary CompileDynamicExpression = new(); - - public void ClearCache() - { - CompileGenericExpression.Clear(); - CompileDynamicExpression.Clear(); - } - - public T Evaluate(string expression) - { - if (CompileGenericExpression.TryGetValue(expression, out var result)) - { - return (result as IGenericExpression).Evaluate(); - } - var compile = context.CompileGeneric(expression); - CompileGenericExpression[expression] = compile; - return compile.Evaluate(); - } - - public object Evaluate(string expression) - { - if (CompileDynamicExpression.TryGetValue(expression, out var result)) - { - return result.Evaluate(); - } - var compile = context.CompileDynamic(expression); - CompileDynamicExpression[expression] = compile; - return compile.Evaluate(); - } - } -} diff --git a/Convention/[RScript]/PublicTypes/RScriptException.cs b/Convention/[RScript]/PublicTypes/RScriptException.cs deleted file mode 100644 index 35422f0..0000000 --- a/Convention/[RScript]/PublicTypes/RScriptException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Convention.RScript -{ - [Serializable] - public class RScriptException : Exception - { - public RScriptException(string message, int runtimePointer) : base($"when running {runtimePointer}, {message}") { } - public RScriptException(string message, int runtimePointer, Exception inner) : base($"when running {runtimePointer}, {message}", inner) { } - } -} diff --git a/Convention/[RScript]/PublicTypes/RScriptImportClass.cs b/Convention/[RScript]/PublicTypes/RScriptImportClass.cs deleted file mode 100644 index 1b0dee7..0000000 --- a/Convention/[RScript]/PublicTypes/RScriptImportClass.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace Convention.RScript -{ - public class RScriptImportClass : ICollection - { - private readonly HashSet importedTypes = new(); - private readonly Dictionary> cacheImportedFunctions = new(); - - public int Count => ((ICollection)importedTypes).Count; - - public bool IsReadOnly => ((ICollection)importedTypes).IsReadOnly; - - private void DoAdd(Type type) - { - foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public)) - { - if (cacheImportedFunctions.ContainsKey(method.Name) == false) - cacheImportedFunctions.Add(method.Name, new()); - cacheImportedFunctions[method.Name].Add(method); - } - } - - public Type[] GetImports() - { - return importedTypes.ToArray(); - } - - public int CountMethod(string methodName) - { - return cacheImportedFunctions.TryGetValue(methodName, out var list) ? list.Count : 0; - } - - public MethodInfo GetMethod(string methodName) - { - if (cacheImportedFunctions.TryGetValue(methodName, out var list)) - { - if (list.Count != 1) - { - throw new AmbiguousMatchException($"Have more than one {methodName} is imported"); - } - return list[0]; - } - return null; - } - - public MethodInfo GetMethodByReturn(string methodName, Type returnType) - { - if (cacheImportedFunctions.TryGetValue(methodName, out var list)) - { - var query = from item in list where item.ReturnType == returnType select item; - if (query.Count() != 1) - { - throw new AmbiguousMatchException($"Have more than one {methodName} is imported"); - } - return query.First(); - } - return null; - } - - public MethodInfo GetMethod(string methodName, params Type[] parameters) - { - static bool Pr(Type[] parameters1, Type[] parameters2) - { - if (parameters1.Length != parameters2.Length) - return false; - for (int i = 0, e = parameters1.Length; i != e; i++) - { - if (parameters1[i] != parameters2[i]) - return false; - } - return true; - } - - if (cacheImportedFunctions.TryGetValue(methodName, out var list)) - { - var query = from item in list - where Pr((from _param in item.GetParameters() select _param.ParameterType).ToArray(), parameters) - select item; - if (query.Count() != 1) - { - throw new AmbiguousMatchException($"Have more than one {methodName} is imported"); - } - return query.First(); - } - return null; - } - - public bool TryAdd(Type type) - { - var stats = importedTypes.Add(type); - if (stats) - { - DoAdd(type); - } - return stats; - } - - public void Add(Type type) - { - TryAdd(type); - } - - public IEnumerator GetEnumerator() - { - return ((IEnumerable)importedTypes).GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)importedTypes).GetEnumerator(); - } - - public void Clear() - { - ((ICollection)importedTypes).Clear(); - } - - public bool Contains(Type item) - { - return ((ICollection)importedTypes).Contains(item); - } - - public void CopyTo(Type[] array, int arrayIndex) - { - ((ICollection)importedTypes).CopyTo(array, arrayIndex); - } - - public bool Remove(Type item) - { - return ((ICollection)importedTypes).Remove(item); - } - } -} diff --git a/Convention/[RScript]/PublicTypes/RScriptVariables.cs b/Convention/[RScript]/PublicTypes/RScriptVariables.cs deleted file mode 100644 index 2502924..0000000 --- a/Convention/[RScript]/PublicTypes/RScriptVariables.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Convention.RScript -{ - public struct RScriptVariableEntry - { - public Type type; - public object data; - } - public class RScriptVariables : IDictionary - { - private readonly Dictionary> variables = new(); - - public RScriptVariableEntry this[string key] - { - get - { - return variables[key].Peek(); - } - set - { - var current = variables[key].Peek(); - if (current.type != value.type) - throw new ArgumentException($"current type is {current.type}, but setter.value is {value.type}"); - variables[key].Pop(); - variables[key].Push(value); - } - } - - public ICollection Keys => variables.Keys; - - public ICollection Values => (from item in variables.Values select item.Peek()).ToArray(); - - public int Count => variables.Count; - - public bool IsReadOnly => false; - - public void Add(string key, RScriptVariableEntry value) - { - if (variables.ContainsKey(key) == false) - variables.Add(key, new()); - variables[key].Push(value); - } - - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - public void ClearAllLayers() - { - variables.Clear(); - } - - /// - /// - /// - public void Clear() - { - ClearAllLayers(); - } - - public bool Contains(KeyValuePair item) - { - if (variables.TryGetValue(item.Key, out var items)) - { - var current = items.Peek(); - return current.data == item.Value.data; - } - return false; - } - - public bool ContainsKey(string key) - { - return variables.ContainsKey(key); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - foreach (var (key, items) in variables) - { - array[arrayIndex++] = new(key, items.Peek()); - } - } - - public IEnumerator> GetEnumerator() - { - return (from items in variables select new KeyValuePair(items.Key, items.Value.Peek())).GetEnumerator(); - } - - public bool Remove(string key) - { - if (variables.TryGetValue(key, out var items)) - { - items.Pop(); - if (items.Count == 0) - { - variables.Remove(key); - } - return true; - } - return false; - } - - public bool Remove(KeyValuePair item) - { - if (variables.TryGetValue(item.Key, out var items)) - { - if (item.Value.data == items.Peek().data) - { - items.Pop(); - if (items.Count == 0) - { - variables.Remove(item.Key); - } - return true; - } - } - return false; - } - - public bool TryGetValue(string key, [MaybeNullWhen(false)] out RScriptVariableEntry value) - { - if (variables.TryGetValue(key, out var items)) - { - value = items.Peek(); - return true; - } - value = default; - return false; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void SetValue(string varName, object value) - { - var top = variables[varName].Pop(); - top.data = value; - variables[varName].Push(top); - } - } -} diff --git a/Convention/[RScript]/RScriptContext.cs b/Convention/[RScript]/RScriptContext.cs deleted file mode 100644 index f122ffa..0000000 --- a/Convention/[RScript]/RScriptContext.cs +++ /dev/null @@ -1,368 +0,0 @@ -using Convention.RScript.Matcher; -using Convention.RScript.Parser; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Convention.RScript -{ - public struct RScriptSentence - { - public enum Mode - { - /// - /// 表达式, 格式: 任意合法表达式 - /// - Expression, - /// - /// 定义变量, 格式: 类型 变量名 - /// 类型支持: string, int, double, float, bool, var - /// 每层命名空间中不可重复定义变量, 不可使用未定义的变量, 不存在时会自动向上查找上级空间的变量 - /// - DefineVariable, - /// - /// 进入新的命名空间, 格式: { - /// 命名空间是一对花括号包裹内容空间, 格式: {...} - /// - EnterNamespace, - /// - /// 退出当前命名空间, 格式: } - /// 命名空间是一对花括号包裹内容空间, 格式: {...} - /// - ExitNamespace, - /// - /// 标签, 格式: label(labelname) - /// - Label, - /// - /// 跳转到指定标签, 格式: goto(boolean,labelname) - /// 判断为真时跳转到labelname - /// - Goto, - /// - /// 跳转到当前命名空间的结束位置, 格式: break(boolean); - /// - Breakpoint, - /// - /// 跳转到上次跳转的位置的后一个位置, 格式: back(boolean); - /// - Backpoint, - } - - public string content; - public List info; - public Mode mode; - } - - public interface IRSentenceMatcher - { - bool Match(string expression, ref RScriptSentence sentence); - } - - public partial class RScriptContext - { - public readonly RScriptImportClass Import; - public readonly RScriptVariables Variables; - private readonly RScriptSentence[] Sentences; - private readonly Dictionary Labels; - private readonly Dictionary Namespace; - - public List SentenceParser = new() - { - new NamespaceMater(), - new DefineVariableMatcher(), - new LabelMatcher(), - new GotoMatcher(), - new BreakMatcher(), - new BackMatcher(), - }; - - private RScriptSentence ParseToSentence(string expression) - { - RScriptSentence result = new() - { - content = expression, - mode = RScriptSentence.Mode.Expression - }; - expression = expression.Trim(); - expression.TrimEnd(';'); - SentenceParser.Any(matcher => matcher.Match(expression, ref result)); - return result; - } - - private void BuildUpLabelsAndNamespace(ref Dictionary labelIndicator, ref Dictionary namespaceIndicator) - { - Stack namespaceLayers = new(); - for (int i = 0, e = Sentences.Length; i != e; i++) - { - if (Sentences[i].mode == RScriptSentence.Mode.Label) - { - labelIndicator[Sentences[i].content] = i; - } - else if (Sentences[i].mode == RScriptSentence.Mode.EnterNamespace) - { - namespaceLayers.Push(i); - } - else if (Sentences[i].mode == RScriptSentence.Mode.ExitNamespace) - { - if (namespaceLayers.Count == 0) - throw new RScriptException("Namespace exit without enter.", i); - var enterPointer = namespaceLayers.Pop(); - namespaceIndicator[enterPointer] = i; - } - } - if (namespaceLayers.Count > 0) - { - throw new RScriptException("Namespace enter without exit.", namespaceLayers.Peek()); - } - } - - public RScriptContext(string[] expressions, RScriptImportClass import = null, RScriptVariables variables = null) - { - this.Import = import ?? new(); - this.Variables = variables ?? new(); - this.Sentences = (from item in expressions select ParseToSentence(item)).ToArray(); - this.Labels = new(); - this.Namespace = new(); - BuildUpLabelsAndNamespace(ref this.Labels, ref this.Namespace); - } - - - public RScriptSentence CurrentSentence => Sentences[CurrentRuntimePointer]; - - private void DoDefineVariable(ExpressionParser parser, RScriptSentence sentence) - { - // 定义变量 - var varTypeName = sentence.info[0]; - var varName = sentence.info[1]; - Type varType; - object varDefaultValue; - { - if (varTypeName == "string") - { - varType = typeof(string); - varDefaultValue = string.Empty; - } - else if (varTypeName == "int") - { - varType = typeof(int); - varDefaultValue = 0; - } - else if (varTypeName == "double") - { - varType = typeof(double); - varDefaultValue = 0.0; - } - else if (varTypeName == "float") - { - varType = typeof(float); - varDefaultValue = 0.0f; - } - else if (varTypeName == "bool") - { - varType = typeof(bool); - varDefaultValue = false; - } - else if (varTypeName == "var") - { - varType = typeof(object); - varDefaultValue = new object(); - } - else - { - throw new RScriptException($"Unsupported variable type '{varTypeName}'.", CurrentRuntimePointer); - } - } - if (CurrentLocalSpaceVariableNames.Peek().Contains(varName) == false) - { - Variables.Add(varName, new() { type = varType, data = varDefaultValue }); - parser.context.Variables[varName] = varDefaultValue; - CurrentLocalSpaceVariableNames.Peek().Add(varName); - } - else - { - throw new RScriptException($"Variable '{varName}' already defined on this namespace.", CurrentRuntimePointer); - } - } - - private void DoEnterNamespace(ExpressionParser parser) - { - // 准备记录当前命名空间中定义的变量, 清空上层命名空间的变量 - CurrentLocalSpaceVariableNames.Push(new()); - // 更新变量值 - foreach (var (varName, varValue) in parser.context.Variables) - { - Variables.SetValue(varName, varValue); - } - // 压栈 - RuntimePointerStack.Push(CurrentRuntimePointer); - } - - private void DoExitNamespace(ExpressionParser parser) - { - // 移除当前命名空间的变量 - foreach (var local in CurrentLocalSpaceVariableNames.Peek()) - { - Variables.Remove(local); - parser.context.Variables.Remove(local); - } - // 还原上层命名空间的变量 - foreach (var local in CurrentLocalSpaceVariableNames.Peek()) - { - parser.context.Variables[local] = Variables[local].data; - } - CurrentLocalSpaceVariableNames.Pop(); - // 弹栈 - RuntimePointerStack.Pop(); - } - - private void DoJumpRuntimePointer(ExpressionParser parser, int target) - { - bool isForwardMove = target > CurrentRuntimePointer; - int step = isForwardMove ? 1 : -1; - for (; CurrentRuntimePointer != target; CurrentRuntimePointer += step) - { - if (CurrentSentence.mode == RScriptSentence.Mode.ExitNamespace) - { - if (isForwardMove) - DoExitNamespace(parser); - else - DoEnterNamespace(parser); - } - else if (CurrentSentence.mode == RScriptSentence.Mode.EnterNamespace) - { - if (isForwardMove) - DoEnterNamespace(parser); - else - DoExitNamespace(parser); - } - } - } - - private void DoGoto(ExpressionParser parser, RScriptSentence sentence) - { - // 检查并跳转到指定标签 - if (parser.Evaluate(sentence.info[0])) - { - if (Labels.TryGetValue(sentence.content, out var labelPointer)) - { - GotoPointerStack.Push(CurrentRuntimePointer); - DoJumpRuntimePointer(parser, labelPointer); - } - else - { - throw new RScriptException($"Label '{sentence.content}' not found.", CurrentRuntimePointer); - } - } - } - - private void DoBreakpoint(ExpressionParser parser, RScriptSentence sentence) - { - // 检查并跳转到当前命名空间的结束位置 - if (parser.Evaluate(sentence.content)) - { - if (RuntimePointerStack.Count == 0) - { - CurrentRuntimePointer = Sentences.Length; - } - else if (Namespace.TryGetValue(RuntimePointerStack.Peek(), out var exitPointer)) - { - CurrentRuntimePointer = exitPointer; - DoExitNamespace(parser); - } - else - { - throw new NotImplementedException($"No namespace to break."); - } - } - } - - private void DoBackpoint(ExpressionParser parser, RScriptSentence sentence) - { - // 检查并跳转到上次跳转的位置 - if (parser.Evaluate(sentence.content)) - { - if (GotoPointerStack.Count == 0) - { - throw new NotImplementedException($"No position to back."); - } - else - { - DoJumpRuntimePointer(parser, GotoPointerStack.Pop()); - } - } - } - - private void RunNextStep(ExpressionParser parser) - { - var sentence = CurrentSentence; - switch (sentence.mode) - { - case RScriptSentence.Mode.Expression: - { - // 执行表达式 - parser.Evaluate(sentence.content); - } - break; - case RScriptSentence.Mode.DefineVariable: - { - DoDefineVariable(parser, sentence); - } - break; - case RScriptSentence.Mode.EnterNamespace: - { - DoEnterNamespace(parser); - } - break; - case RScriptSentence.Mode.ExitNamespace: - { - DoExitNamespace(parser); - } - break; - case RScriptSentence.Mode.Goto: - { - DoGoto(parser, sentence); - } - break; - case RScriptSentence.Mode.Breakpoint: - { - DoBreakpoint(parser,sentence); - } - break; - case RScriptSentence.Mode.Backpoint: - { - DoBackpoint(parser, sentence); - } - break; - default: - // Do nothing - break; - } - } - - private readonly Stack RuntimePointerStack = new(); - private readonly Stack GotoPointerStack = new(); - private int CurrentRuntimePointer = 0; - private readonly Stack> CurrentLocalSpaceVariableNames = new(); - - public Dictionary Run(ExpressionParser parser) - { - CurrentLocalSpaceVariableNames.Clear(); - RuntimePointerStack.Clear(); - GotoPointerStack.Clear(); - CurrentLocalSpaceVariableNames.Clear(); - CurrentLocalSpaceVariableNames.Push(new()); - for (CurrentRuntimePointer = 0; CurrentRuntimePointer < Sentences.Length; CurrentRuntimePointer++) - { - RunNextStep(parser); - } - // 更新上下文变量 - foreach (var (varName, varValue) in parser.context.Variables) - { - if (Variables.ContainsKey(varName)) - Variables.SetValue(varName, varValue); - } - return Variables.ToDictionary(); - } - } -} diff --git a/Convention/[RScript]/RScriptEngine.cs b/Convention/[RScript]/RScriptEngine.cs deleted file mode 100644 index 7ed71ee..0000000 --- a/Convention/[RScript]/RScriptEngine.cs +++ /dev/null @@ -1,111 +0,0 @@ -using Convention.RScript.Parser; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace Convention.RScript -{ - public class RScriptEngine - { - private ExpressionParser parser; - private RScriptContext context; - - private IEnumerable SplitScript(string script) - { - StringBuilder builder = new(); - List statements = new(); - - for (int i = 0, e = script.Length; i < e; i++) - { - char c = script[i]; - if (c == ';') - { - if (builder.Length > 0) - { - statements.Add(builder.ToString().Trim()); - builder.Clear(); - } - } - else if (c == '/' && i + 1 < e) - { - // Skip single-line comment - if (script[i + 1] == '/') - { - while (i < script.Length && script[i] != '\n') - i++; - } - // Skip multi-line comment - else if (script[i + 1] == '*') - { - i += 2; - while (i + 1 < script.Length && !(script[i] == '*' && script[i + 1] == '/')) - i++; - i++; - } - else - { - builder.Append(c); - } - } - else if (c == '#') - { - // Skip single-line comment - while (i < script.Length && script[i] != '\n') - i++; - } - else if (c == '\"') - { - for (i++; i < e; i++) - { - builder.Append(script[i]); - if (script[i] == '\"') - { - break; - } - else if (script[i] == '\\') - { - i++; - if (i < e) - builder.Append(script[i]); - else - throw new RScriptException("Invalid escape sequence in string literal", -1); - } - } - } - else if (c == '{' || c == '}') - { - // Treat braces as statement separators - if (builder.Length > 0) - { - statements.Add(builder.ToString().Trim()); - builder.Clear(); - } - statements.Add(c.ToString()); - } - else - { - builder.Append(c); - } - } - if (builder.Length > 0) - { - statements.Add(builder.ToString().Trim()); - builder.Clear(); - } - - return statements.Where(s => !string.IsNullOrWhiteSpace(s)); - } - - public Dictionary Run(string script, RScriptImportClass import = null, RScriptVariables variables = null) - { - parser = new(new()); - context = new(SplitScript(script).ToArray(), import, variables); - foreach (var type in context.Import) - parser.context.Imports.AddType(type); - return context.Run(parser); - } - } -}