From a72c6b285b29bcc18f029bf3cdc94ce043913efb Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Thu, 24 Jul 2025 09:35:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=A5=E7=A6=BBSymbolization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Convention/[Runtime]/File.cs | 94 +--- .../[Symbolization]/Detail/Exception.cs | 16 - .../[Symbolization]/Detail/Functional.cs | 97 ---- Convention/[Symbolization]/Detail/Keyword.cs | 524 ------------------ .../[Symbolization]/Detail/Namespace.cs | 185 ------- .../[Symbolization]/Detail/PrimitiveType.cs | 57 -- .../Detail/ScriptWordVariable.cs | 26 - .../[Symbolization]/Detail/Structure.cs | 87 --- Convention/[Symbolization]/Detail/Variable.cs | 116 ---- .../Runner/SymbolizationContext.cs | 71 --- .../Runner/SymbolizationReader.cs | 137 ----- Convention/[Symbolization]/Symbolization.cs | 18 - 12 files changed, 3 insertions(+), 1425 deletions(-) delete mode 100644 Convention/[Symbolization]/Detail/Exception.cs delete mode 100644 Convention/[Symbolization]/Detail/Functional.cs delete mode 100644 Convention/[Symbolization]/Detail/Keyword.cs delete mode 100644 Convention/[Symbolization]/Detail/Namespace.cs delete mode 100644 Convention/[Symbolization]/Detail/PrimitiveType.cs delete mode 100644 Convention/[Symbolization]/Detail/ScriptWordVariable.cs delete mode 100644 Convention/[Symbolization]/Detail/Structure.cs delete mode 100644 Convention/[Symbolization]/Detail/Variable.cs delete mode 100644 Convention/[Symbolization]/Runner/SymbolizationContext.cs delete mode 100644 Convention/[Symbolization]/Runner/SymbolizationReader.cs delete mode 100644 Convention/[Symbolization]/Symbolization.cs diff --git a/Convention/[Runtime]/File.cs b/Convention/[Runtime]/File.cs index 155a3b9..c027103 100644 --- a/Convention/[Runtime]/File.cs +++ b/Convention/[Runtime]/File.cs @@ -1,19 +1,14 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text.Json; using System.IO.Compression; +using System.Linq; using System.Security.Cryptography; using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using System.ComponentModel; -using System.Runtime.InteropServices; +using System.Text.Json; namespace Convention { - // 自定义异常类 public class FileOperationException : Exception { public FileOperationException(string message) : base(message) { } @@ -84,7 +79,6 @@ namespace Convention )..]; } - // 新增:获取文件名(对应 Python 的 GetFilename) public string GetFilename(bool is_without_extension = false) { if (is_without_extension && Path.HasExtension(FullPath)) @@ -101,25 +95,21 @@ namespace Convention } } - // 新增:获取目录路径(对应 Python 的 GetDir) public string GetDir() { return Path.GetDirectoryName(FullPath); } - // 新增:获取目录的 ToolFile 对象(对应 Python 的 GetDirToolFile) public ToolFile GetDirToolFile() { return new ToolFile(GetDir()); } - // 新增:获取当前目录名(对应 Python 的 GetCurrentDirName) public string GetCurrentDirName() { return Path.GetDirectoryName(FullPath); } - // 新增:获取父目录(对应 Python 的 GetParentDir) public ToolFile GetParentDir() { return new ToolFile(GetDir()); @@ -185,7 +175,6 @@ namespace Convention return result; } - // 新增:加载为 CSV(使用 C# 内置功能) public List LoadAsCsv() { if (IsFile() == false) @@ -203,13 +192,11 @@ namespace Convention return result; } - // 新增:加载为 XML(使用 C# 内置功能) public string LoadAsXml() { return LoadAsText(); } - // 新增:加载为 Excel(简化实现,实际需要第三方库) public string LoadAsExcel() { // 注意:真正的 Excel 读取需要第三方库如 EPPlus 或 NPOI @@ -217,7 +204,6 @@ namespace Convention return LoadAsText(); } - // 新增:加载为未知格式(对应 Python 的 LoadAsUnknown) public string LoadAsUnknown(string suffix) { return LoadAsText(); @@ -262,7 +248,6 @@ namespace Convention SaveDataAsBinary(FullPath, data, (OriginInfo as FileInfo).OpenWrite()); } - // 新增:保存为 CSV(对应 Python 的 SaveAsCsv) public void SaveAsCsv(List csvData) { if (IsFile() == false) @@ -272,25 +257,21 @@ namespace Convention File.WriteAllLines(FullPath, lines); } - // 新增:保存为 XML(对应 Python 的 SaveAsXml) public void SaveAsXml(string xmlData) { SaveAsText(xmlData); } - // 新增:保存为 Excel(简化实现) public void SaveAsExcel(string excelData) { SaveAsText(excelData); } - // 新增:保存为数据框(对应 Python 的 SaveAsDataframe) public void SaveAsDataframe(List dataframeData) { SaveAsCsv(dataframeData); } - // 新增:保存为未知格式(对应 Python 的 SaveAsUnknown) public void SaveAsUnknown(object unknownData) { if (unknownData is byte[] bytes) @@ -328,7 +309,6 @@ namespace Convention #region Size and Properties - // 新增:获取文件大小(对应 Python 的 GetSize) public long GetSize() { if (IsDir()) @@ -376,7 +356,6 @@ namespace Convention return new ToolFile(Path.Combine(lp, rightPath)); } - // 新增:相等比较(对应 Python 的 __eq__) public override bool Equals(object obj) { if (obj is ToolFile other) @@ -447,7 +426,6 @@ namespace Convention return this; } - // 新增:复制方法重载(对应 Python 的 Copy) public ToolFile Copy(string targetPath = null) { if (targetPath == null) @@ -495,7 +473,6 @@ namespace Convention return this; } - // 新增:Remove 方法(对应 Python 的 Remove) public ToolFile Remove() { return Delete(); @@ -567,7 +544,6 @@ namespace Convention return this; } - // 新增:MakeFileInside 方法(对应 Python 的 MakeFileInside) public ToolFile MakeFileInside(ToolFile data, bool is_delete_source = false) { if (!IsDir()) @@ -582,7 +558,6 @@ namespace Convention return this; } - // 新增:查找文件方法(对应 Python 的 FirstFileWithExtension) public ToolFile FirstFileWithExtension(string extension) { var targetDir = IsDir() ? this : GetDirToolFile(); @@ -596,7 +571,6 @@ namespace Convention return null; } - // 新增:查找文件方法(对应 Python 的 FirstFile) public ToolFile FirstFile(Func predicate) { var targetDir = IsDir() ? this : GetDirToolFile(); @@ -610,7 +584,6 @@ namespace Convention return null; } - // 新增:查找所有文件方法(对应 Python 的 FindFileWithExtension) public List FindFileWithExtension(string extension) { var targetDir = IsDir() ? this : GetDirToolFile(); @@ -625,7 +598,6 @@ namespace Convention return result; } - // 新增:查找所有文件方法(对应 Python 的 FindFile) public List FindFile(Func predicate) { var targetDir = IsDir() ? this : GetDirToolFile(); @@ -644,7 +616,6 @@ namespace Convention #region Compression - // 新增:压缩方法(对应 Python 的 Compress) public ToolFile Compress(string outputPath = null, string format = "zip") { if (!Exists()) @@ -684,7 +655,6 @@ namespace Convention } } - // 新增:解压方法(对应 Python 的 Decompress) public ToolFile Decompress(string outputPath = null) { if (!Exists() || !IsFile()) @@ -713,7 +683,6 @@ namespace Convention #region Encryption - // 新增:加密方法(对应 Python 的 Encrypt) public ToolFile Encrypt(string key, string algorithm = "AES") { if (!Exists() || !IsFile()) @@ -759,7 +728,6 @@ namespace Convention } } - // 新增:解密方法(对应 Python 的 decrypt) public ToolFile Decrypt(string key, string algorithm = "AES") { if (!Exists() || !IsFile()) @@ -813,7 +781,6 @@ namespace Convention #region Hash - // 新增:计算哈希值(对应 Python 的 calculate_hash) public string CalculateHash(string algorithm = "MD5", int chunkSize = 8192) { if (!Exists() || !IsFile()) @@ -846,14 +813,12 @@ namespace Convention }; } - // 新增:验证哈希值(对应 Python 的 verify_hash) public bool VerifyHash(string expectedHash, string algorithm = "MD5") { string actualHash = CalculateHash(algorithm); return string.Equals(actualHash, expectedHash, StringComparison.OrdinalIgnoreCase); } - // 新增:保存哈希值(对应 Python 的 save_hash) public ToolFile SaveHash(string algorithm = "MD5", string outputPath = null) { string hash = CalculateHash(algorithm); @@ -873,7 +838,6 @@ namespace Convention #region File Monitoring - // 新增:文件监控(简化实现,对应 Python 的 start_monitoring) public void StartMonitoring(Action callback, bool recursive = false, List ignorePatterns = null, bool ignoreDirectories = false, bool caseSensitive = true, bool isLog = true) @@ -890,7 +854,7 @@ namespace Convention }; watcher.Created += (sender, e) => callback("created", e.FullPath); - watcher.Modified += (sender, e) => callback("modified", e.FullPath); + watcher.Changed += (sender, e) => callback("modified", e.FullPath); watcher.Deleted += (sender, e) => callback("deleted", e.FullPath); watcher.Renamed += (sender, e) => callback("moved", e.FullPath); } @@ -899,7 +863,6 @@ namespace Convention #region Backup - // 新增:创建备份(对应 Python 的 create_backup) public ToolFile CreateBackup(string backupDir = null, int maxBackups = 5, string backupFormat = "zip", bool includeMetadata = true) { @@ -956,7 +919,6 @@ namespace Convention } } - // 新增:恢复备份(对应 Python 的 restore_backup) public ToolFile RestoreBackup(string backupFile, string restorePath = null, bool verifyHash = true) { var backupToolFile = new ToolFile(backupFile); @@ -987,7 +949,6 @@ namespace Convention } } - // 新增:列出备份(对应 Python 的 list_backups) public List ListBackups(string backupDir = null) { if (backupDir == null) @@ -1009,7 +970,6 @@ namespace Convention #region Permissions - // 新增:获取权限(对应 Python 的 get_permissions) public Dictionary GetPermissions() { if (!Exists()) @@ -1038,7 +998,6 @@ namespace Convention return permissions; } - // 新增:设置权限(对应 Python 的 set_permissions) public ToolFile SetPermissions(bool? read = null, bool? write = null, bool? execute = null, bool? hidden = null, bool recursive = false) { @@ -1084,7 +1043,6 @@ namespace Convention } } - // 新增:权限检查方法(对应 Python 的 is_readable, is_writable 等) public bool IsReadable() { try @@ -1148,56 +1106,10 @@ namespace Convention var sourceFile = new ToolFile(source); return MakeFileInside(sourceFile, isDeleteSource); } - public static string[] SelectMultipleFiles(string filter = "所有文件|*.*", string title = "选择文件") - { - using var dialog = new OpenFileDialog - { - Filter = filter, - Title = title, - Multiselect = true - }; - return dialog.ShowDialog() == DialogResult.OK ? dialog.FileNames : new string[0]; - } - public static string SelectFile(string filter = "所有文件|*.*", string title = "选择文件") - { - using var dialog = new OpenFileDialog - { - Filter = filter, - Title = title - }; - return dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null; - } - public static string SaveFile(string filter = "所有文件|*.*", string title = "保存文件") - { - using var dialog = new SaveFileDialog - { - Filter = filter, - Title = title - }; - return dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null; - } - public static string SelectFolder(string description = "请选择文件夹") - { - using var dialog = new FolderBrowserDialog - { - Description = description - }; - return dialog.ShowDialog() == DialogResult.OK ? dialog.SelectedPath : null; - } public DateTime GetTimestamp() { return (OriginInfo as FileInfo)?.LastWriteTime ?? DateTime.MinValue; } - public static string BrowseFile(params string[] extensions) - { - string filter = string.Join("|", extensions.Select(ext => $"{ext.ToUpper()} 文件|*.{ext}")); - return SelectFile(filter); - } - public static ToolFile BrowseToolFile(params string[] extensions) - { - string path = BrowseFile(extensions); - return path != null ? new ToolFile(path) : null; - } #endregion } diff --git a/Convention/[Symbolization]/Detail/Exception.cs b/Convention/[Symbolization]/Detail/Exception.cs deleted file mode 100644 index 465b0d2..0000000 --- a/Convention/[Symbolization]/Detail/Exception.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace Convention.Symbolization -{ - - [Serializable] - public class InvalidGrammarException : Exception - { - public InvalidGrammarException() { } - public InvalidGrammarException(string message) : base(message) { } - public InvalidGrammarException(string message, Exception inner) : base(message, inner) { } - protected InvalidGrammarException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) : base(info, context) { } - } -} diff --git a/Convention/[Symbolization]/Detail/Functional.cs b/Convention/[Symbolization]/Detail/Functional.cs deleted file mode 100644 index 33062c7..0000000 --- a/Convention/[Symbolization]/Detail/Functional.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; - -namespace Convention.Symbolization.Internal -{ - public abstract class Function : CloneableVariable - { - public readonly FunctionSymbol FunctionInfo; - - protected Function(string symbolName,int lineIndex,int wordIndex,string functionName, Type returnType, Type[] parameterTypes) : base(symbolName, lineIndex, wordIndex) - { - FunctionInfo = new(functionName, returnType, parameterTypes); - } - public abstract Variable Invoke(SymbolizationContext context, Variable[] parameters); - } - - public sealed class DelegationalFunction : Function - { - public readonly MethodInfo methodInfo; - - public DelegationalFunction(string symbolName, int lineIndex, int wordIndex, MethodInfo methodInfo) - : base(symbolName, lineIndex, wordIndex, - methodInfo.Name, methodInfo.ReturnType, methodInfo.GetParameters().ToList().ConvertAll(x => x.ParameterType).ToArray()) - { - this.methodInfo = methodInfo!; - } - - public override DelegationalFunction CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new DelegationalFunction(targetSymbolName, lineIndex, wordIndex, methodInfo); - } - - public override bool Equals(Function other) - { - return other is DelegationalFunction df && df.methodInfo == this.methodInfo; - } - - public override Variable Invoke(SymbolizationContext context, Variable[] parameters) - { - Variable invoker = parameters.Length > 0 ? parameters[0] : null; - Variable[] invokerParameters = parameters.Length > 0 ? parameters.Skip(1).ToArray() : Array.Empty(); - object result = methodInfo.Invoke(invoker, invokerParameters); - return result as Variable; - } - } - - public sealed class ScriptFunction : Function - { - public ScriptFunction(string symbolName, int lineIndex, int wordIndex, - string functionName, Type returnType, Type[] parameterTypes) - : base(symbolName, lineIndex, wordIndex, functionName, returnType, parameterTypes) - { - } - - public override Function CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - throw new NotImplementedException(); - } - - public override bool Equals(Function other) - { - throw new NotImplementedException(); - } - - public override Variable Invoke(SymbolizationContext context, Variable[] parameters) - { - throw new NotImplementedException(); - } - } - - public readonly struct FunctionSymbol - { - public readonly string FunctionName; - public readonly Type ReturnType; - public readonly Type[] ParameterTypes; - public readonly string FullName; - - public FunctionSymbol(string symbolName, Type returnType, Type[] parameterTypes) - { - this.FunctionName = symbolName; - this.ReturnType = returnType; - this.ParameterTypes = parameterTypes; - this.FullName = $"{returnType.FullName} {symbolName}({string.Join(',', parameterTypes.ToList().ConvertAll(x => x.FullName))})"; - } - - public bool Equals(FunctionSymbol other) - { - return other.FullName.Equals(FullName); - } - - public override int GetHashCode() - { - return FullName.GetHashCode(); - } - } -} diff --git a/Convention/[Symbolization]/Detail/Keyword.cs b/Convention/[Symbolization]/Detail/Keyword.cs deleted file mode 100644 index d8eb6ee..0000000 --- a/Convention/[Symbolization]/Detail/Keyword.cs +++ /dev/null @@ -1,524 +0,0 @@ -using System.Collections.Generic; -using System.IO; - -namespace Convention.Symbolization.Internal -{ - public abstract class Keyword : CloneableVariable - { - protected Keyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) { } - - public static readonly Dictionary Keywords = new() - { - { "import", new Convention.Symbolization.Keyword.Import(0,0) }, - { "namespace", new Convention.Symbolization.Keyword.Namespace(0,0) }, - { "def", new Convention.Symbolization.Keyword.FunctionDef(0,0) }, - { "return", new Convention.Symbolization.Keyword.Return(0,0) }, - { "if", new Convention.Symbolization.Keyword.If(0,0) }, - { "elif", new Convention.Symbolization.Keyword.Elif(0,0) }, - { "else", new Convention.Symbolization.Keyword.Else(0,0) }, - { "while", new Convention.Symbolization.Keyword.While(0,0) }, - { "break", new Convention.Symbolization.Keyword.Break(0,0) }, - { "continue", new Convention.Symbolization.Keyword.Continue(0,0) }, - { "struct", new Convention.Symbolization.Keyword.Structure(0,0) } - }; - - public override bool Equals(Keyword other) - { - return this.GetType() == other.GetType(); - } - - public abstract bool ControlScope(Variable next); - - public abstract void BuildScope(SymbolizationContext context, List scopeWords); - } - - public abstract class Keyword : Keyword where T : Keyword - { - protected Keyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) { } - - public override bool Equals(Variable other) - { - return other is T; - } - } -} - -namespace Convention.Symbolization.Keyword -{ - public abstract class SingleKeyword : Internal.Keyword where T : SingleKeyword - { - protected SingleKeyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) - { - } - public override bool ControlScope(Internal.Variable next) - { - if (next is Internal.ScriptWordVariable swv && swv.Word == ";") - return true; - throw new InvalidGrammarException($"Expected ';' but got {next}"); - } - - public abstract void BuildScope(); - - public sealed override void BuildScope(SymbolizationContext context, List scopeWords) - { - BuildScope(); - } - } - - public abstract class SentenceKeyword : Internal.Keyword where T : SentenceKeyword - { - protected SentenceKeyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) - { - } - public override bool ControlScope(Internal.Variable next) - { - if (next is not Internal.ScriptWordVariable swv) - throw new InvalidGrammarException($"Not expected a key Word: {next}"); - return swv.Word != ";"; - } - - public abstract void BuildSentence(SymbolizationContext context, List sentence); - - public sealed override void BuildScope(SymbolizationContext context, List scopeWords) - { - BuildSentence(context, scopeWords.GetRange(0, scopeWords.Count - 1)); - } - } - - public abstract class NamespaceKeyword : Internal.Keyword where T : NamespaceKeyword - { - protected NamespaceKeyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) - { - } - private enum Pause - { - Name, Body - } - - private Pause pause = Pause.Name; - private int layer = 0; - - public override bool ControlScope(Internal.Variable next) - { - if (pause == Pause.Name) - { - if (next is Internal.ScriptWordVariable swv) - { - if (swv.Word == "{") - { - pause = Pause.Body; - layer++; - } - return true; - } - else - { - throw new InvalidGrammarException($"Expected a script Word variable for namespace name, but got {next}"); - } - } - else - { - if (next is Internal.ScriptWordVariable swv) - { - if (swv.Word == "{") - layer++; - else if (swv.Word == "}") - layer--; - if (layer == 0) - { - return false; - } - } - return true; - } - } - - public abstract void BuildSpace( - SymbolizationContext context, - List spaceExpression, - Dictionary scopeStartAndEnd, - List insideScopeWords - ); - - public override void BuildScope(SymbolizationContext context, List scopeWords) - { - List spaceExpression = new(); - Dictionary scopeStartAndEnd = new(); - Stack stack = new(); - bool IsSpaceExpression = true; - foreach (var word in scopeWords) - { - var swv = word as Internal.ScriptWordVariable; - if (IsSpaceExpression) - { - if (swv.Word == "{") - { - IsSpaceExpression = false; - stack.Push(swv); - layer++; - } - else - { - spaceExpression.Add(swv); - } - } - else - { - if (swv.Word == "{") - { - stack.Push(swv); - layer++; - } - else if (swv.Word == "}") - { - scopeStartAndEnd.Add(stack.Pop(), swv); - layer--; - } - } - } - BuildSpace(context, spaceExpression, scopeStartAndEnd, - scopeWords.GetRange(spaceExpression.Count, scopeWords.Count - spaceExpression.Count)); - } - } - - public abstract class VerbObjectScopeKeyword : Internal.Keyword where T : VerbObjectScopeKeyword - { - protected VerbObjectScopeKeyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) - { - } - - private enum Pause - { - BeforeExpression, Expression, BeforeBody, Body, SingleSentence - } - - private Pause pause = Pause.BeforeExpression; - private int layer = 0; - - public override bool ControlScope(Internal.Variable next) - { - if (pause == Pause.BeforeExpression) - { - if (next is not Internal.ScriptWordVariable swv) - throw new InvalidGrammarException($"Not expected a key Word: {next}"); - if (swv.Word == "(") - pause = Pause.Expression; - else - throw new InvalidGrammarException($"Expected '(' symbol for expression start, but got {next}"); - } - else if (pause == Pause.Expression) - { - if (next is Internal.ScriptWordVariable swv && swv.Word == ")") - { - pause = Pause.BeforeBody; - } - } - else if (pause == Pause.BeforeBody) - { - if (next is Internal.ScriptWordVariable swv && swv.Word == "{") - { - pause = Pause.Body; - layer++; - } - else - pause = Pause.SingleSentence; - } - else if (pause == Pause.Body) - { - if (next is Internal.ScriptWordVariable swv) - { - if (swv.Word == "{") - layer++; - else if (swv.Word == "}") - layer--; - if (layer == 0) - return false; - } - } - else if (pause == Pause.SingleSentence) - { - if (next is Internal.ScriptWordVariable swv && swv.Word == ";") - { - return false; - } - } - return true; - } - - public abstract void BuildSpace( - SymbolizationContext context, - List spaceExpression, - Dictionary scopeStartAndEnd, - List insideScopeWords - ); - - public override void BuildScope(SymbolizationContext context, List scopeWords) - { - var pause = Pause.BeforeExpression; - List expression = new(); - Dictionary scopeStartAndEnd = new(); - List insideScopeWords = new(); - Stack stack = new(); - foreach (var word in scopeWords) - { - if (pause == Pause.BeforeExpression) - { - pause = Pause.Expression; - } - else if (pause == Pause.Expression) - { - if (word is Internal.ScriptWordVariable swv && swv.Word == ")") - { - pause = Pause.BeforeBody; - } - else - { - expression.Add(word); - } - } - else if (pause == Pause.BeforeBody) - { - if (word is Internal.ScriptWordVariable swv && swv.Word == "{") - { - pause = Pause.Body; - stack.Push(word); - } - else - { - pause = Pause.SingleSentence; - insideScopeWords.Add(word); - } - } - else if (pause == Pause.Body) - { - if (word is Internal.ScriptWordVariable swv) - { - if (swv.Word == "{") - stack.Push(word); - else if (swv.Word == "}") - scopeStartAndEnd.Add(stack.Pop(), word); - } - else - insideScopeWords.Add(word); - } - else if (pause == Pause.SingleSentence) - { - insideScopeWords.Add(word); - } - } - BuildSpace(context, expression, scopeStartAndEnd, insideScopeWords); - } - } - - /// - /// file - /// - public sealed class Import : SentenceKeyword - { - public Import(int lineIndex, int wordIndex) : base("import", lineIndex, wordIndex) - { - } - - public override void BuildSentence(SymbolizationContext context, List sentence) - { - ToolFile importPath = new(string.Join('/', sentence.ConvertAll(x => (x as Internal.ScriptWordVariable).Word))); - if(importPath.Exists()==false) - throw new FileNotFoundException(importPath.ToString()); - new SymbolizationContext(context).Compile(importPath); - } - - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Import(lineIndex, wordIndex); - } - } - - /// - /// name { ... } - /// - public sealed class Namespace : NamespaceKeyword - { - public Namespace(int lineIndex, int wordIndex) : base("namespace", lineIndex, wordIndex) - { - } - - public override void BuildSpace( - SymbolizationContext context, - List spaceExpression, - Dictionary scopeStartAndEnd, - List insideScopeWords - ) - { - //TODO - //将命名空间放在新的子上下文中编译 - } - - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Namespace(lineIndex, wordIndex); - } - } - - /// - /// FunctionName(parameter-list) return-type { ... return return-type-instance; } - /// - public sealed class FunctionDef : NamespaceKeyword - { - public FunctionDef(int lineIndex, int wordIndex) : base("def", lineIndex, wordIndex) - { - } - - public override void BuildSpace( - SymbolizationContext context, - List spaceExpression, - Dictionary scopeStartAndEnd, - List insideScopeWords - ) - { - //TODO - //套用语法规则实现表达式向可执行语句的转换 - } - - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new FunctionDef(lineIndex, wordIndex); - } - } - - /// - /// symbol; - /// - public sealed class Return : SentenceKeyword - { - public Return(int lineIndex, int wordIndex) : base("return", lineIndex, wordIndex) - { - } - - public override void BuildSentence(SymbolizationContext context, List sentence) - { - var symbol = sentence[0]; - //TODO - //直接转换为可执行语句 - //在上下文中搜索被返回的symbol, 存在则返回对应对象, 不存在则返回symbol对象 - //运行时检查返回值是否满足函数签名的返回值, 否则抛出异常 - } - - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Return(lineIndex, wordIndex); - } - } - - /// - /// (bool-expression) expression - /// - public sealed class If : VerbObjectScopeKeyword - { - public If(int lineIndex, int wordIndex) : base("if", lineIndex, wordIndex) - { - } - - public override void BuildSpace( - SymbolizationContext context, - List spaceExpression, - Dictionary scopeStartAndEnd, - List insideScopeWords - ) - { - //TODO - //检查表达式是否成功, 成功则套用函数翻译规则将作用域翻译为可执行语句 - //否则跳转到末尾 - } - - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new If(lineIndex, wordIndex); - } - } - - /// - /// expression expression - /// expression expression expression... - /// - public sealed class Elif : VerbObjectScopeKeyword - { - public Elif(int lineIndex, int wordIndex) : base("elif", lineIndex, wordIndex) - { - } - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Elif(lineIndex, wordIndex); - } - } - - /// - /// expression expression - /// expression expression... expression - /// - public sealed class Else : NamespaceKeyword - { - public Else(int lineIndex, int wordIndex) : base("else", lineIndex, wordIndex) - { - } - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Else(lineIndex, wordIndex); - } - } - - /// - /// (bool-expression) expression - /// - public sealed class While : VerbObjectScopeKeyword - { - public While(int lineIndex, int wordIndex) : base("while", lineIndex, wordIndex) - { - } - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new While(lineIndex, wordIndex); - } - } - - /// - /// ; - /// - public sealed class Break : SingleKeyword - { - public Break(int lineIndex, int wordIndex) : base("break", lineIndex, wordIndex) - { - } - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Break(lineIndex, wordIndex); - } - } - - /// - /// ; - /// - public sealed class Continue : SingleKeyword - { - public Continue(int lineIndex, int wordIndex) : base("continue", lineIndex, wordIndex) - { - } - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Continue(lineIndex, wordIndex); - } - } - - /// - /// structureName { ... } - /// - public sealed class Structure : NamespaceKeyword - { - public Structure(int lineIndex, int wordIndex) : base("struct", lineIndex, wordIndex) - { - } - public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new Structure(lineIndex, wordIndex); - } - } -} diff --git a/Convention/[Symbolization]/Detail/Namespace.cs b/Convention/[Symbolization]/Detail/Namespace.cs deleted file mode 100644 index f5cd7fc..0000000 --- a/Convention/[Symbolization]/Detail/Namespace.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Convention.Symbolization.Internal -{ - public sealed class Namespace : Variable, ICanFindVariable - { - private int Updateable = 0; - - public void BeginUpdate() - { - Updateable++; - } - - private readonly Dictionary SubNamespaces = new(); - private readonly Dictionary Functions = new(); - private readonly Dictionary Structures = new(); - - public Namespace CreateOrGetSubNamespace(string subNamespace) - { - if (Updateable == 0) - throw new InvalidOperationException("Cannot create sub-namespace outside of an update block."); - if(!SubNamespaces.TryGetValue(subNamespace,out var result)) - { - result = new Namespace(subNamespace); - SubNamespaces[subNamespace] = result; - } - return result; - } - - public void AddFunction(Function function) - { - if (Updateable == 0) - throw new InvalidOperationException("Cannot add function outside of an update block."); - ArgumentNullException.ThrowIfNull(function); - Functions.Add(function.FunctionInfo, function); - } - - public void AddStructure(Structure structure) - { - if (Updateable == 0) - throw new InvalidOperationException("Cannot add structure outside of an update block."); - ArgumentNullException.ThrowIfNull(structure); - Structures.Add(structure.SymbolInfo.SymbolName, structure); - } - - public bool EndAndTryApplyUpdate() - { - Updateable--; - if (Updateable == 0) - Refresh(); - return Updateable == 0; - } - - private readonly Dictionary SymbolCounter = new(); - private readonly Dictionary> Symbol2Variable = new(); - - public void Refresh() - { - // Refresh Symbols - SymbolCounter.Clear(); - foreach (var ns in SubNamespaces) - { - ns.Value.Refresh(); - foreach (var symbol in ns.Value.SymbolCounter) - { - if (SymbolCounter.ContainsKey(symbol.Key)) - SymbolCounter[symbol.Key] += symbol.Value; - else - SymbolCounter[symbol.Key] = symbol.Value; - } - foreach (var symbol in ns.Value.Symbol2Variable) - { - if (Symbol2Variable.TryGetValue(symbol.Key, out List value)) - value.AddRange(symbol.Value); - else - Symbol2Variable[symbol.Key] = new(symbol.Value); - } - } - foreach (var func in Functions) - { - { - if (SymbolCounter.TryGetValue(func.Key.FunctionName, out var value)) - SymbolCounter[func.Key.FunctionName] = ++value; - else - SymbolCounter[func.Key.FunctionName] = 1; - } - { - if (Symbol2Variable.TryGetValue(func.Key.FunctionName, out var value)) - value.Add(func.Value); - else - Symbol2Variable[func.Key.FunctionName] = new() { func.Value }; - } - { - if (Symbol2Variable.TryGetValue(func.Key.FunctionName, out var value)) - value.Add(func.Value); - else - Symbol2Variable[func.Key.FunctionName] = new() { func.Value }; - } - } - foreach (var @struct in Structures) - { - { - if (SymbolCounter.TryGetValue(@struct.Key, out int value)) - SymbolCounter[@struct.Key] = ++value; - else - SymbolCounter[@struct.Key] = 1; - } - { - if (Symbol2Variable.TryGetValue(@struct.Key, out List value)) - value.Add(@struct.Value); - else - Symbol2Variable[@struct.Key] = new() { @struct.Value }; - } - } - } - - public static Namespace CreateRootNamespace() - { - return new("global", 0, 0); - } - - private Namespace(string symbolName, int lineIndex, int wordIndex) : base(symbolName, lineIndex, wordIndex) { } - - public override bool Equals(Namespace other) - { - return this == other; - } - - public string GetNamespaceName() => this.SymbolInfo.SymbolName; - - public bool ContainsSymbol(string symbolName) - { - return SymbolCounter.ContainsKey(symbolName); - } - - public int CountSymbol(string symbolName) - { - return SymbolCounter.TryGetValue(symbolName, out var count) ? count : 0; - } - - public Variable[] Find(string symbolName) - { - if (!Symbol2Variable.TryGetValue(symbolName,out var result)) - return Array.Empty(); - return result.ToArray(); - } - - public Namespace FindSubNamespace(string subNamespaceName) - { - if (!SubNamespaces.TryGetValue(subNamespaceName, out var result)) - return null; - return result; - } - - public Function[] FindFunction(string symbolName) - { - if (!Symbol2Variable.TryGetValue(symbolName, out var result)) - return Array.Empty(); - return result.OfType().ToArray(); - } - - public Function FindFunctionInNamespace(FunctionSymbol symbol) - { - if (!Functions.TryGetValue(symbol, out var result)) - return null; - return result; - } - - public Structure[] FindStructure(string symbolName) - { - if (!Symbol2Variable.TryGetValue(symbolName, out var result)) - return Array.Empty(); - return result.OfType().ToArray(); - } - - public Structure FindStructureInNamespace(string symbolName) - { - if (!Structures.TryGetValue(symbolName, out var result)) - return null; - return result; - } - } -} diff --git a/Convention/[Symbolization]/Detail/PrimitiveType.cs b/Convention/[Symbolization]/Detail/PrimitiveType.cs deleted file mode 100644 index 9382c4d..0000000 --- a/Convention/[Symbolization]/Detail/PrimitiveType.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; - -namespace Convention.Symbolization.Primitive -{ - public class PrimitiveType : Internal.Variable - { - public PrimitiveType() : base(new(typeof(T).Name, typeof(T), 0, 0)) - { - } - - public override bool Equals(Internal.Variable other) - { - return other is PrimitiveType; - } - - public virtual T CloneValue(T value) - { - if (Utility.IsNumber(typeof(T))) - return value; - else if (Utility.IsString(typeof(T))) - return (T)(object)new string((string)(object)value); - else if (value is ICloneable cloneable) - return (T)cloneable.Clone(); - else if (value is Internal.Variable) - return value; - return value; - } - - public virtual T DefaultValue() => default; - } - - public class PrimitiveInstance : Internal.CloneableVariable> - { - private readonly PrimitiveType MyPrimitiveType = new(); - public T Value; - - public PrimitiveInstance(string symbolName,int lineIndex,int wordIndex, T value, PrimitiveType primitiveType) : base(symbolName, lineIndex, wordIndex) - { - this.Value = value; - this.MyPrimitiveType = primitiveType; - } - - public override PrimitiveInstance CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new(targetSymbolName, lineIndex, wordIndex, MyPrimitiveType.CloneValue(this.Value), this.MyPrimitiveType); - } - - public override bool Equals(PrimitiveInstance other) - { - return this.Value.Equals(other.Value); - } - public override string ToString() - { - return Value.ToString(); - } - } -} diff --git a/Convention/[Symbolization]/Detail/ScriptWordVariable.cs b/Convention/[Symbolization]/Detail/ScriptWordVariable.cs deleted file mode 100644 index fc66393..0000000 --- a/Convention/[Symbolization]/Detail/ScriptWordVariable.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Convention.Symbolization.Internal -{ - public class ScriptWordVariable : CloneableVariable - { - public string Word => this.SymbolInfo.SymbolName; - - public ScriptWordVariable(string word, int lineIndex, int wordIndex) : base((string)word.Clone(), lineIndex, wordIndex) - { - } - - public override ScriptWordVariable CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new ScriptWordVariable(Word, lineIndex, wordIndex); - } - - public override bool Equals(ScriptWordVariable other) - { - return other is not null && Word.Equals(other.Word); - } - - public override string ToString() - { - return Word; - } - } -} diff --git a/Convention/[Symbolization]/Detail/Structure.cs b/Convention/[Symbolization]/Detail/Structure.cs deleted file mode 100644 index 21bb2fd..0000000 --- a/Convention/[Symbolization]/Detail/Structure.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Convention.Symbolization.Internal -{ - public sealed class Structure : Variable, ICanFindVariable - { - private Dictionary MemberFields; - public readonly Namespace ParentNamespace; - - public Dictionary CloneMemberFields() - { - return new(from pair in MemberFields - select new KeyValuePair( - pair.Key, - pair.Value is ICloneable cloneable ? (cloneable.Clone() as Variable) : pair.Value) - ); - } - - private Structure(string symbolName, int lineIndex,int wordIndex, Namespace parentNamespace) : base(symbolName, lineIndex, wordIndex) - { - this.ParentNamespace = parentNamespace; - } - - public static Structure Create(VariableSymbol symbol, Namespace parent) - { - Structure result = new(symbol.SymbolName, symbol.LineIndex, symbol.WordIndex, parent); - parent.AddStructure(result); - return result; - } - - public override bool Equals(Structure other) - { - return this == other; - } - - public Variable[] Find(string symbolName) - { - if (MemberFields.TryGetValue(symbolName, out var variable)) - { - return new[] { variable }; - } - return Array.Empty(); - } - } - - public sealed class StructureInstance : CloneableVariable,ICanFindVariable - { - public readonly Structure StructureType; - private readonly Dictionary MemberFields; - public StructureInstance(string symbolName, int lineIndex, int wordIndex, Structure structureType) - : base(symbolName, lineIndex, wordIndex) - { - this.StructureType = structureType; - this.MemberFields = structureType.CloneMemberFields(); - } - public override bool Equals(StructureInstance other) - { - return this == other; - } - public override StructureInstance CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new StructureInstance(targetSymbolName, lineIndex, wordIndex, this.StructureType); - } - - public Variable GetField(string memberName) - { - if (MemberFields.TryGetValue(memberName, out var result)) - return result; - else - throw new KeyNotFoundException($"Member '{memberName}' not found in structure '{StructureType.SymbolInfo.SymbolName}'."); - } - - public Variable[] Find(string symbolName) - { - if (MemberFields.TryGetValue(symbolName, out var variable)) - { - return new[] { variable }; - } - return Array.Empty(); - } - } -} - diff --git a/Convention/[Symbolization]/Detail/Variable.cs b/Convention/[Symbolization]/Detail/Variable.cs deleted file mode 100644 index 8eed324..0000000 --- a/Convention/[Symbolization]/Detail/Variable.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; - -namespace Convention.Symbolization.Internal -{ - public abstract class Variable : IEquatable - { - public readonly VariableSymbol SymbolInfo; - - protected Variable(VariableSymbol symbolInfo) - { - this.SymbolInfo = symbolInfo; - } - - public abstract bool Equals(Variable other); - - public override bool Equals(object obj) - { - return Equals(obj as Variable); - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - public override string ToString() - { - return SymbolInfo.SymbolName; - } - } - - - public abstract class Variable : Variable, IEquatable - { - protected Variable(string symbolName, int lineIndex, int wordIndex) : base(new VariableSymbol(symbolName, typeof(T), lineIndex, wordIndex)) { } - public abstract bool Equals(T other); - - public override bool Equals(Variable other) - { - return other is T variable && Equals(variable); - } - - public override bool Equals(object obj) - { - return obj is T variable && Equals(variable); - } - - public virtual int GetVariableHashCode() - { - return base.GetHashCode(); - } - - public override sealed int GetHashCode() - { - return GetVariableHashCode(); - } - } - - public interface ICanFindVariable - { - public Variable[] Find(string symbolName); - } - - public abstract class CloneableVariable : Variable, ICloneable - { - protected CloneableVariable(string symbolName, int lineIndex, int wordIndex) : base(symbolName, lineIndex, wordIndex) - { - } - - public object Clone() => CloneVariable(SymbolInfo.SymbolName, 0, 0); - - public abstract T CloneVariable(string targetSymbolName, int lineIndex, int wordIndex); - } - - public sealed class NullVariable : CloneableVariable - { - public NullVariable(string symbolName, int lineIndex, int wordIndex) : base(symbolName, lineIndex, wordIndex) - { - } - - public override NullVariable CloneVariable(string targetSymbolName, int lineIndex, int wordIndex) - { - return new(targetSymbolName, lineIndex, wordIndex); - } - - public override bool Equals(NullVariable other) - { - return true; - } - } - - public readonly struct VariableSymbol - { - public readonly int LineIndex; - public readonly int WordIndex; - public readonly string SymbolName; - public readonly Type VariableType; - - public VariableSymbol(string symbolName, Type variableType, int lineIndex,int wordIndex) - { - this.SymbolName = symbolName; - this.VariableType = variableType; - this.LineIndex = lineIndex; - this.WordIndex = wordIndex; - } - - public bool Equals(VariableSymbol other) - { - return other.SymbolName.Equals(SymbolName) && other.VariableType.Equals(VariableType); - } - - public override int GetHashCode() - { - return new Tuple(SymbolName, VariableType).GetHashCode(); - } - } -} diff --git a/Convention/[Symbolization]/Runner/SymbolizationContext.cs b/Convention/[Symbolization]/Runner/SymbolizationContext.cs deleted file mode 100644 index 7c8878b..0000000 --- a/Convention/[Symbolization]/Runner/SymbolizationContext.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Convention.Symbolization -{ - public class SymbolizationContext - { - public SymbolizationContext() : this(null, Internal.Namespace.CreateRootNamespace()) { } - public SymbolizationContext(SymbolizationContext parent) : this(parent, parent.CurrentNamespace) { } - public SymbolizationContext(SymbolizationContext parent, Internal.Namespace newNamespace) - { - this.ParentContext = parent; - this.CurrentNamespace = newNamespace; - } - - private readonly SymbolizationContext ParentContext; - public readonly Internal.Namespace CurrentNamespace; - - private void CompileToParent() - { - if (ParentContext == null) - return; - } - - // Compile begin at scope words to sub context - public void Compile(Dictionary> scopeWords) - { - foreach (var (keyword, words) in scopeWords) - { - - } - } - - // Compile begin at script words to scope words - private void CompileBeginAtScript2Scope(Internal.SymbolizationReader reader) - { - foreach (var word in reader.ScriptWords) - { - reader.ReadWord(word); - } - this.Compile(reader.ScopeWords); - } - - // Compile begin at script words to scope words - public void Compile(List scriptWords) - { - this.CompileBeginAtScript2Scope(new() { ScriptWords = scriptWords }); - } - - // Compile begin at text to script words - public void Compile(string allText) - { - Internal.SymbolizationReader reader = new(); - reader ??= new(); - foreach (char ch in allText) - reader.ReadChar(ch); - // Turn the script words into scope words - this.CompileBeginAtScript2Scope(reader); - } - - // Compile begin at text to script words - public void Compile(ToolFile file) - { - if (file.Exists() == false) - throw new FileNotFoundException($"File not found: {file}", file); - var text = file.LoadAsText(); - this.Compile(text); - } - } -} diff --git a/Convention/[Symbolization]/Runner/SymbolizationReader.cs b/Convention/[Symbolization]/Runner/SymbolizationReader.cs deleted file mode 100644 index 45f0801..0000000 --- a/Convention/[Symbolization]/Runner/SymbolizationReader.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Convention.Symbolization.Internal -{ - public class SymbolizationReader - { - #region Read Script Words - - private string buffer = ""; - private int lineContext = 1; - private int wordContext = 0; - private bool isOutOfStringline = true; - public List ScriptWords = new(); - - private readonly static HashSet ControllerCharSet = new() - { - '{','}','(',')','[',']', - '+','-','*','/','%', - '=', - '!','<','>','&','|', - '^', - ':',',','.','?',/*'\'','"',*/ - '@','#','$', - ';' - }; - - public void ReadChar(char ch) - { - if (isOutOfStringline) - { - if (ControllerCharSet.Contains(ch)) - CompleteSingleSymbol(ch); - else if (ch == '\n') - CompleteLine(); - else if (char.IsWhiteSpace(ch) || ch == '\r' || ch == '\t') - CompleteWord(); - else if (buffer.Length == 0 && ch == '"') - BeginString(); - else if (char.IsLetter(ch) || char.IsDigit(ch)) - PushChar(ch); - else - throw new NotImplementedException($"{lineContext + 1} line, {buffer} + <{ch}> not implemented"); - } - else - { - if ((buffer.Length > 0 && buffer.Last() == '\\') || ch != '"') - PushChar(ch); - else if (ch == '"') - EndString(); - else - throw new NotImplementedException($"{lineContext + 1} line, \"{buffer}\" + \'{ch}\' not implemented"); - } - } - - void CompleteSingleSymbol(char ch) - { - CompleteWord(); - buffer = ch.ToString(); - CompleteWord(); - } - void PushChar(char ch) - { - buffer += ch; - } - void CompleteWord() - { - if (buffer.Length > 0) - { - if (Internal.Keyword.Keywords.TryGetValue(buffer, out var keyword)) - { - ScriptWords.Add(keyword.CloneVariable(buffer, lineContext, wordContext)); - } - else - { - ScriptWords.Add(new ScriptWordVariable(buffer, lineContext, wordContext + 1)); - } - buffer = ""; - wordContext++; - } - } - void CompleteLine() - { - CompleteWord(); - lineContext++; - wordContext = 0; - } - void BeginString() - { - if (buffer.Length > 0) - throw new InvalidGrammarException($"String must start with nothing: {buffer}"); - isOutOfStringline = false; - } - void EndString() - { - isOutOfStringline = true; - CompleteWord(); - } - - #endregion - - #region Read Scope Words - - public Dictionary> ScopeWords = new(); - public Keyword currentKey = null; - public bool isNextKeyword = true; - - public void ReadWord(Variable word) - { - if (isNextKeyword) - { - if (word is Keyword cky) - { - currentKey = cky; - ScopeWords.Add(currentKey, new()); - isNextKeyword = false; - } - else - { - throw new InvalidGrammarException( - $"Line {word.SymbolInfo.LineIndex}, Word {word.SymbolInfo.WordIndex}: Expected a keyword, but got {word}" - ); - } - } - else - { - ScopeWords[currentKey].Add(word); - isNextKeyword = currentKey.ControlScope(word) == false; - } - } - - #endregion - } -} diff --git a/Convention/[Symbolization]/Symbolization.cs b/Convention/[Symbolization]/Symbolization.cs deleted file mode 100644 index dedcdc5..0000000 --- a/Convention/[Symbolization]/Symbolization.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Text; -using System.Threading.Tasks; - -namespace Convention.Symbolization -{ - public class SymbolizationRunner - { - private SymbolizationContext Context; - - public void Compile(string path) - { - Context = new(); - Context.Compile(new ToolFile(path)); - } - - } -}