剥离Symbolization
This commit is contained in:
@@ -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<string[]> 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<string[]> 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<string[]> 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<string, bool> predicate)
|
||||
{
|
||||
var targetDir = IsDir() ? this : GetDirToolFile();
|
||||
@@ -610,7 +584,6 @@ namespace Convention
|
||||
return null;
|
||||
}
|
||||
|
||||
// 新增:查找所有文件方法(对应 Python 的 FindFileWithExtension)
|
||||
public List<ToolFile> FindFileWithExtension(string extension)
|
||||
{
|
||||
var targetDir = IsDir() ? this : GetDirToolFile();
|
||||
@@ -625,7 +598,6 @@ namespace Convention
|
||||
return result;
|
||||
}
|
||||
|
||||
// 新增:查找所有文件方法(对应 Python 的 FindFile)
|
||||
public List<ToolFile> FindFile(Func<string, bool> 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<string, string> callback, bool recursive = false,
|
||||
List<string> 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<ToolFile> ListBackups(string backupDir = null)
|
||||
{
|
||||
if (backupDir == null)
|
||||
@@ -1009,7 +970,6 @@ namespace Convention
|
||||
|
||||
#region Permissions
|
||||
|
||||
// 新增:获取权限(对应 Python 的 get_permissions)
|
||||
public Dictionary<string, bool> 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
|
||||
}
|
||||
|
@@ -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) { }
|
||||
}
|
||||
}
|
@@ -1,97 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Convention.Symbolization.Internal
|
||||
{
|
||||
public abstract class Function : CloneableVariable<Function>
|
||||
{
|
||||
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<Variable>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,524 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Convention.Symbolization.Internal
|
||||
{
|
||||
public abstract class Keyword : CloneableVariable<Keyword>
|
||||
{
|
||||
protected Keyword(string keyword, int lineIndex, int wordIndex) : base(keyword, lineIndex, wordIndex) { }
|
||||
|
||||
public static readonly Dictionary<string, Keyword> 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<Variable> scopeWords);
|
||||
}
|
||||
|
||||
public abstract class Keyword<T> : Keyword where T : Keyword<T>
|
||||
{
|
||||
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<T> : Internal.Keyword<T> where T : SingleKeyword<T>
|
||||
{
|
||||
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<Internal.Variable> scopeWords)
|
||||
{
|
||||
BuildScope();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SentenceKeyword<T> : Internal.Keyword<T> where T : SentenceKeyword<T>
|
||||
{
|
||||
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<Internal.Variable> sentence);
|
||||
|
||||
public sealed override void BuildScope(SymbolizationContext context, List<Internal.Variable> scopeWords)
|
||||
{
|
||||
BuildSentence(context, scopeWords.GetRange(0, scopeWords.Count - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class NamespaceKeyword<T> : Internal.Keyword<T> where T : NamespaceKeyword<T>
|
||||
{
|
||||
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<Internal.ScriptWordVariable> spaceExpression,
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd,
|
||||
List<Internal.Variable> insideScopeWords
|
||||
);
|
||||
|
||||
public override void BuildScope(SymbolizationContext context, List<Internal.Variable> scopeWords)
|
||||
{
|
||||
List<Internal.ScriptWordVariable> spaceExpression = new();
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd = new();
|
||||
Stack<Internal.Variable> 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<T> : Internal.Keyword<T> where T : VerbObjectScopeKeyword<T>
|
||||
{
|
||||
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<Internal.Variable> spaceExpression,
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd,
|
||||
List<Internal.Variable> insideScopeWords
|
||||
);
|
||||
|
||||
public override void BuildScope(SymbolizationContext context, List<Internal.Variable> scopeWords)
|
||||
{
|
||||
var pause = Pause.BeforeExpression;
|
||||
List<Internal.Variable> expression = new();
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd = new();
|
||||
List<Internal.Variable> insideScopeWords = new();
|
||||
Stack<Internal.Variable> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="import"/> file</b>
|
||||
/// </summary>
|
||||
public sealed class Import : SentenceKeyword<Import>
|
||||
{
|
||||
public Import(int lineIndex, int wordIndex) : base("import", lineIndex, wordIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildSentence(SymbolizationContext context, List<Internal.Variable> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="namespace"/> name { ... }</b>
|
||||
/// </summary>
|
||||
public sealed class Namespace : NamespaceKeyword<Namespace>
|
||||
{
|
||||
public Namespace(int lineIndex, int wordIndex) : base("namespace", lineIndex, wordIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildSpace(
|
||||
SymbolizationContext context,
|
||||
List<Internal.ScriptWordVariable> spaceExpression,
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd,
|
||||
List<Internal.Variable> insideScopeWords
|
||||
)
|
||||
{
|
||||
//TODO
|
||||
//将命名空间放在新的子上下文中编译
|
||||
}
|
||||
|
||||
public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex)
|
||||
{
|
||||
return new Namespace(lineIndex, wordIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="def"/> FunctionName(parameter-list) return-type { ... return return-type-instance; }</b>
|
||||
/// </summary>
|
||||
public sealed class FunctionDef : NamespaceKeyword<FunctionDef>
|
||||
{
|
||||
public FunctionDef(int lineIndex, int wordIndex) : base("def", lineIndex, wordIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildSpace(
|
||||
SymbolizationContext context,
|
||||
List<Internal.ScriptWordVariable> spaceExpression,
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd,
|
||||
List<Internal.Variable> insideScopeWords
|
||||
)
|
||||
{
|
||||
//TODO
|
||||
//套用语法规则实现表达式向可执行语句的转换
|
||||
}
|
||||
|
||||
public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex)
|
||||
{
|
||||
return new FunctionDef(lineIndex, wordIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="return"/> symbol;</b>
|
||||
/// </summary>
|
||||
public sealed class Return : SentenceKeyword<Return>
|
||||
{
|
||||
public Return(int lineIndex, int wordIndex) : base("return", lineIndex, wordIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildSentence(SymbolizationContext context, List<Internal.Variable> sentence)
|
||||
{
|
||||
var symbol = sentence[0];
|
||||
//TODO
|
||||
//直接转换为可执行语句
|
||||
//在上下文中搜索被返回的symbol, 存在则返回对应对象, 不存在则返回symbol对象
|
||||
//运行时检查返回值是否满足函数签名的返回值, 否则抛出异常
|
||||
}
|
||||
|
||||
public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex)
|
||||
{
|
||||
return new Return(lineIndex, wordIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="if"/>(bool-expression) expression</b>
|
||||
/// </summary>
|
||||
public sealed class If : VerbObjectScopeKeyword<If>
|
||||
{
|
||||
public If(int lineIndex, int wordIndex) : base("if", lineIndex, wordIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildSpace(
|
||||
SymbolizationContext context,
|
||||
List<Internal.Variable> spaceExpression,
|
||||
Dictionary<Internal.Variable, Internal.Variable> scopeStartAndEnd,
|
||||
List<Internal.Variable> insideScopeWords
|
||||
)
|
||||
{
|
||||
//TODO
|
||||
//检查表达式是否成功, 成功则套用函数翻译规则将作用域翻译为可执行语句
|
||||
//否则跳转到末尾
|
||||
}
|
||||
|
||||
public override Internal.Keyword CloneVariable(string targetSymbolName, int lineIndex, int wordIndex)
|
||||
{
|
||||
return new If(lineIndex, wordIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="if"/> expression <see langword="elif"/> expression</b><para></para>
|
||||
/// <b><see langword="if"/> expression <see langword="elif"/> expression <see langword="elif"/> expression...</b>
|
||||
/// </summary>
|
||||
public sealed class Elif : VerbObjectScopeKeyword<Elif>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="if"/> expression <see langword="else"/> expression</b><para></para>
|
||||
/// <b><see langword="if"/> expression <see langword="elif"/> expression... <see langword="else"/> expression</b>
|
||||
/// </summary>
|
||||
public sealed class Else : NamespaceKeyword<Else>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="while"/>(bool-expression) expression</b>
|
||||
/// </summary>
|
||||
public sealed class While : VerbObjectScopeKeyword<While>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="break"/>;</b>
|
||||
/// </summary>
|
||||
public sealed class Break : SingleKeyword<Break>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="continue"/>;</b>
|
||||
/// </summary>
|
||||
public sealed class Continue : SingleKeyword<Continue>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <b><see langword="struct"/> structureName { ... }</b>
|
||||
/// </summary>
|
||||
public sealed class Structure : NamespaceKeyword<Structure>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,185 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Convention.Symbolization.Internal
|
||||
{
|
||||
public sealed class Namespace : Variable<Namespace>, ICanFindVariable
|
||||
{
|
||||
private int Updateable = 0;
|
||||
|
||||
public void BeginUpdate()
|
||||
{
|
||||
Updateable++;
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, Namespace> SubNamespaces = new();
|
||||
private readonly Dictionary<FunctionSymbol, Function> Functions = new();
|
||||
private readonly Dictionary<string, Structure> 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<string, int> SymbolCounter = new();
|
||||
private readonly Dictionary<string, List<Variable>> 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<Variable> 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<Variable> 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<Variable>();
|
||||
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<Function>();
|
||||
return result.OfType<Function>().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<Structure>();
|
||||
return result.OfType<Structure>().ToArray();
|
||||
}
|
||||
|
||||
public Structure FindStructureInNamespace(string symbolName)
|
||||
{
|
||||
if (!Structures.TryGetValue(symbolName, out var result))
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Convention.Symbolization.Primitive
|
||||
{
|
||||
public class PrimitiveType<T> : Internal.Variable
|
||||
{
|
||||
public PrimitiveType() : base(new(typeof(T).Name, typeof(T), 0, 0))
|
||||
{
|
||||
}
|
||||
|
||||
public override bool Equals(Internal.Variable other)
|
||||
{
|
||||
return other is PrimitiveType<T>;
|
||||
}
|
||||
|
||||
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<T> : Internal.CloneableVariable<PrimitiveInstance<T>>
|
||||
{
|
||||
private readonly PrimitiveType<T> MyPrimitiveType = new();
|
||||
public T Value;
|
||||
|
||||
public PrimitiveInstance(string symbolName,int lineIndex,int wordIndex, T value, PrimitiveType<T> primitiveType) : base(symbolName, lineIndex, wordIndex)
|
||||
{
|
||||
this.Value = value;
|
||||
this.MyPrimitiveType = primitiveType;
|
||||
}
|
||||
|
||||
public override PrimitiveInstance<T> CloneVariable(string targetSymbolName, int lineIndex, int wordIndex)
|
||||
{
|
||||
return new(targetSymbolName, lineIndex, wordIndex, MyPrimitiveType.CloneValue(this.Value), this.MyPrimitiveType);
|
||||
}
|
||||
|
||||
public override bool Equals(PrimitiveInstance<T> other)
|
||||
{
|
||||
return this.Value.Equals(other.Value);
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
namespace Convention.Symbolization.Internal
|
||||
{
|
||||
public class ScriptWordVariable : CloneableVariable<ScriptWordVariable>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<Structure>, ICanFindVariable
|
||||
{
|
||||
private Dictionary<string, Variable> MemberFields;
|
||||
public readonly Namespace ParentNamespace;
|
||||
|
||||
public Dictionary<string, Variable> CloneMemberFields()
|
||||
{
|
||||
return new(from pair in MemberFields
|
||||
select new KeyValuePair<string, Variable>(
|
||||
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<Variable>();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class StructureInstance : CloneableVariable<StructureInstance>,ICanFindVariable
|
||||
{
|
||||
public readonly Structure StructureType;
|
||||
private readonly Dictionary<string, Variable> 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<Variable>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,116 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Convention.Symbolization.Internal
|
||||
{
|
||||
public abstract class Variable : IEquatable<Variable>
|
||||
{
|
||||
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<T> : Variable, IEquatable<T>
|
||||
{
|
||||
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<T> : Variable<T>, 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<NullVariable>
|
||||
{
|
||||
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<string, Type>(SymbolName, VariableType).GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<Internal.Keyword, List<Internal.Variable>> 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<Internal.Variable> 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<Variable> ScriptWords = new();
|
||||
|
||||
private readonly static HashSet<char> 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<Keyword, List<Variable>> 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
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user