mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-04 09:06:41 +02:00
- Add tasks
- Add check if file exist - Improved code structure
This commit is contained in:
@@ -1,12 +1,21 @@
|
||||
namespace YesNt.Interpreter
|
||||
using System;
|
||||
|
||||
namespace YesNt.Interpreter
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
YesNtInterpreter interpreter = new YesNtInterpreter();
|
||||
interpreter.Initialize();
|
||||
interpreter.Execute(args[0]);
|
||||
if (args.Length == 1)
|
||||
{
|
||||
YesNtInterpreter interpreter = new YesNtInterpreter();
|
||||
interpreter.Initialize();
|
||||
interpreter.Execute(args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No path specified!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using YesNt.Interpreter.Runtime;
|
||||
using YesNt.Interpreter.Utilities;
|
||||
|
||||
namespace YesNt.Interpreter
|
||||
{
|
||||
internal class RuntimeInformation
|
||||
{
|
||||
private RuntimeInformation parentRuntimeInformation;
|
||||
|
||||
public Dictionary<string, string> Variables { get; } = new();
|
||||
public Dictionary<string, int> Labels { get; } = new();
|
||||
public List<string> Lines { get; set; } = new();
|
||||
@@ -15,15 +18,52 @@ namespace YesNt.Interpreter
|
||||
public string SearchLabel { get; set; } = string.Empty;
|
||||
public int LineNumber { get; set; } = 0;
|
||||
public bool Stop { get; private set; } = false;
|
||||
public bool IsDebugMode { get; set; }
|
||||
public bool StopAllTasks { get; private set; } = false;
|
||||
public bool IsDebugMode { get; set; } = false;
|
||||
public string CurrentFilePath { get; set; } = string.Empty;
|
||||
public bool IsTask => ParentRuntimeInformation is not null;
|
||||
|
||||
public RuntimeInformation ParentRuntimeInformation
|
||||
{
|
||||
get => parentRuntimeInformation;
|
||||
set
|
||||
{
|
||||
parentRuntimeInformation = value;
|
||||
if (parentRuntimeInformation is not null)
|
||||
{
|
||||
parentRuntimeInformation.OnExit += ParentRuntimeInformation_OnExit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private event Action<string, bool> OnExit;
|
||||
|
||||
public event Action<string> OnDebugOutput;
|
||||
|
||||
public event Action<DebugEventArgs> OnLineExecuted;
|
||||
|
||||
private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopChildTasks)
|
||||
{
|
||||
Exit($"Parent task was terminated!", stopChildTasks);
|
||||
}
|
||||
|
||||
public void WriteLine(string output)
|
||||
{
|
||||
if (Stop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsDebugMode)
|
||||
{
|
||||
OnDebugOutput?.Invoke(output.FromSaveString() + Environment.NewLine);
|
||||
if (IsTask)
|
||||
{
|
||||
parentRuntimeInformation.WriteLine(output.FromSaveString() + Environment.NewLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDebugOutput?.Invoke(output.FromSaveString() + Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -33,9 +73,21 @@ namespace YesNt.Interpreter
|
||||
|
||||
public void Write(string output)
|
||||
{
|
||||
if (Stop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsDebugMode)
|
||||
{
|
||||
OnDebugOutput?.Invoke(output.FromSaveString());
|
||||
if (IsTask)
|
||||
{
|
||||
parentRuntimeInformation.Write(output.FromSaveString());
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDebugOutput?.Invoke(output.FromSaveString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -43,21 +95,45 @@ namespace YesNt.Interpreter
|
||||
}
|
||||
}
|
||||
|
||||
public void Exit(string message)
|
||||
public void Exit(string message, bool stopAllTasks)
|
||||
{
|
||||
WriteLine($"{Environment.NewLine}[The process was terminated at line {LineNumber + 1} with the message: {message}]");
|
||||
Stop = true;
|
||||
if (!Stop)
|
||||
{
|
||||
WriteLine($"{Environment.NewLine}[{(IsTask ? "A child task" : "The process")} was terminated at line {LineNumber + 1} with the message: {message}]");
|
||||
Stop = true;
|
||||
}
|
||||
if (stopAllTasks == true && StopAllTasks == false)
|
||||
{
|
||||
StopAllTasks = true;
|
||||
OnExit?.Invoke(message, StopAllTasks);
|
||||
parentRuntimeInformation?.Exit("Terminated by child task", true);
|
||||
}
|
||||
}
|
||||
|
||||
public void LineExecuted(DebugEventArgs debugEventArgs)
|
||||
{
|
||||
if (IsTask)
|
||||
{
|
||||
parentRuntimeInformation.LineExecuted(debugEventArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnLineExecuted?.Invoke(debugEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
CurrentLine = string.Empty;
|
||||
Lines.Clear();
|
||||
Variables.Clear();
|
||||
Labels.Clear();
|
||||
LabelStack.Clear();
|
||||
ParentRuntimeInformation = null;
|
||||
SearchLabel = string.Empty;
|
||||
CurrentFilePath = string.Empty;
|
||||
CurrentLine = string.Empty;
|
||||
Stop = false;
|
||||
StopAllTasks = false;
|
||||
IsDebugMode = false;
|
||||
LineNumber = 0;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ namespace YesNt.Interpreter
|
||||
|
||||
public event Action<string> OnDebugOutput;
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
runtimeInfo.Exit("Terminated by external process", true);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
@@ -80,6 +85,7 @@ namespace YesNt.Interpreter
|
||||
staticStatements = staticStatements.OrderBy(s => s.Key.Priority).ToList();
|
||||
|
||||
runtimeInfo.OnDebugOutput += (s) => OnDebugOutput?.Invoke(s);
|
||||
runtimeInfo.OnLineExecuted += (DebugEventArgs e) => OnLineExecuted.Invoke(e);
|
||||
}
|
||||
|
||||
public void Execute(string path, bool isDebugMode = false)
|
||||
@@ -87,8 +93,27 @@ namespace YesNt.Interpreter
|
||||
runtimeInfo.Reset();
|
||||
runtimeInfo.IsDebugMode = isDebugMode;
|
||||
LoadFile(path);
|
||||
Execute();
|
||||
}
|
||||
|
||||
for (runtimeInfo.LineNumber = 0; runtimeInfo.LineNumber < runtimeInfo.Lines.Count; runtimeInfo.LineNumber++)
|
||||
internal void Execute(List<string> lines, int startLine, RuntimeInformation parentRuntimeInformation)
|
||||
{
|
||||
runtimeInfo.Reset();
|
||||
runtimeInfo.IsDebugMode = parentRuntimeInformation.IsDebugMode;
|
||||
runtimeInfo.Lines = lines;
|
||||
runtimeInfo.LineNumber = startLine;
|
||||
runtimeInfo.ParentRuntimeInformation = parentRuntimeInformation;
|
||||
if (parentRuntimeInformation.StopAllTasks)
|
||||
{
|
||||
runtimeInfo.Exit($"Parent task was terminated!", parentRuntimeInformation.StopAllTasks);
|
||||
return;
|
||||
}
|
||||
Execute();
|
||||
}
|
||||
|
||||
private void Execute()
|
||||
{
|
||||
for (; runtimeInfo.LineNumber < runtimeInfo.Lines.Count; runtimeInfo.LineNumber++)
|
||||
{
|
||||
if (runtimeInfo.Stop)
|
||||
{
|
||||
@@ -173,18 +198,25 @@ namespace YesNt.Interpreter
|
||||
|
||||
if (!statementFound)
|
||||
{
|
||||
runtimeInfo.Exit("Invalid statement");
|
||||
runtimeInfo.Exit("Invalid statement", true);
|
||||
}
|
||||
if (isDebugMode && searchingLabel)
|
||||
if (runtimeInfo.IsDebugMode && searchingLabel)
|
||||
{
|
||||
debugEventArgs.CurrentLine = runtimeInfo.CurrentLine.FromSaveString();
|
||||
OnLineExecuted?.Invoke(debugEventArgs);
|
||||
runtimeInfo.LineExecuted(debugEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
if (runtimeInfo.Stop == false)
|
||||
{
|
||||
runtimeInfo.Exit("End of file");
|
||||
if (string.IsNullOrWhiteSpace(runtimeInfo.SearchLabel))
|
||||
{
|
||||
runtimeInfo.Exit("End of file", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
runtimeInfo.Exit($"Label \"{runtimeInfo.SearchLabel}\" not found", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +224,7 @@ namespace YesNt.Interpreter
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
runtimeInfo.WriteLine($"File \"{path}\" not found!");
|
||||
runtimeInfo.Exit($"File \"{path}\" not found!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using YesNt.Interpreter.Attributes;
|
||||
using YesNt.Interpreter.Enums;
|
||||
using YesNt.Interpreter.Utilities;
|
||||
|
||||
namespace YesNt.Interpreter
|
||||
{
|
||||
internal class Statements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("cwl", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)]
|
||||
public void WriteLine(string args)
|
||||
{
|
||||
RuntimeInfo.WriteLine(args);
|
||||
}
|
||||
|
||||
[Statement("cw", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)]
|
||||
public void Write(string args)
|
||||
{
|
||||
RuntimeInfo.Write(args);
|
||||
}
|
||||
|
||||
[Statement("%crl", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
||||
public void ReadLine(string args)
|
||||
{
|
||||
args += " ";
|
||||
while (args.Contains("%crl "))
|
||||
{
|
||||
args = args.ReplaceFirstOccurrence("%crl ", Console.ReadLine().ToSaveString() + " ");
|
||||
}
|
||||
RuntimeInfo.CurrentLine = args.TrimEnd();
|
||||
}
|
||||
|
||||
[Statement("%cr", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
||||
public void ReadKey(string args)
|
||||
{
|
||||
args += " ";
|
||||
while (args.Contains("%cr "))
|
||||
{
|
||||
args = args.ReplaceFirstOccurrence("%cr ", Console.ReadKey().KeyChar.ToString().ToSaveString() + " ");
|
||||
}
|
||||
RuntimeInfo.CurrentLine = args.TrimEnd();
|
||||
}
|
||||
|
||||
[Statement("jmp", SearchMode.StartOfLine, SpaceAround.End)]
|
||||
public void Jump(string args)
|
||||
{
|
||||
string key = args.Trim();
|
||||
RuntimeInfo.LabelStack.Push(RuntimeInfo.LineNumber);
|
||||
|
||||
if (RuntimeInfo.Labels.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.LineNumber = RuntimeInfo.Labels[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.SearchLabel = key;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("jif", SearchMode.StartOfLine, SpaceAround.End)]
|
||||
public void JumpIf(string args)
|
||||
{
|
||||
string[] parts = args.Split('|');
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid syntax");
|
||||
return;
|
||||
}
|
||||
|
||||
string key = parts[0].Trim();
|
||||
string condition = parts[1].Trim();
|
||||
|
||||
bool? result = Evaluator.EvaluateCondition(condition);
|
||||
|
||||
if (result != true)
|
||||
{
|
||||
if (result is null)
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid operation");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeInfo.LabelStack.Push(RuntimeInfo.LineNumber);
|
||||
|
||||
if (RuntimeInfo.Labels.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.LineNumber = RuntimeInfo.Labels[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.SearchLabel = key;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("lbl", SearchMode.StartOfLine, SpaceAround.End, ExecuteInSearchLabelMode = true)]
|
||||
public void FindLabel(string args)
|
||||
{
|
||||
string key = args.Trim();
|
||||
if (RuntimeInfo.Labels.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.Labels[key] = RuntimeInfo.LineNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Labels.Add(key, RuntimeInfo.LineNumber);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchLabel) && RuntimeInfo.SearchLabel == key)
|
||||
{
|
||||
RuntimeInfo.SearchLabel = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("ret", SearchMode.Exact, SpaceAround.None)]
|
||||
public void Return(string _)
|
||||
{
|
||||
if (RuntimeInfo.LabelStack.Count > 0)
|
||||
{
|
||||
RuntimeInfo.LineNumber = RuntimeInfo.LabelStack.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Exit("No label in stack");
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("end", SearchMode.Exact, SpaceAround.None)]
|
||||
public void End(string _)
|
||||
{
|
||||
RuntimeInfo.Exit("Planned termination by code");
|
||||
}
|
||||
|
||||
[Statement("!calc", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.High, ExecuteInSearchLabelMode = true)]
|
||||
public void Calculate(string args)
|
||||
{
|
||||
MatchCollection matches = Regex.Matches(args, @"((\)?)+(\(?)+[0-9]+(((\s?)+(\)?)(\s?)+\+(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\-(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\*(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\/(\s?)+(\(?)+(\s?)+)|[,.])(?=[0-9])+)+[0-9]+(\)?)+");
|
||||
|
||||
for (int i = 0; i < matches.Count; i++)
|
||||
{
|
||||
string res = Evaluator.Calculate(matches[i].Value);
|
||||
if (res is null)
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid operation");
|
||||
return;
|
||||
}
|
||||
args = args.Replace(matches[0].Value, res);
|
||||
}
|
||||
|
||||
RuntimeInfo.CurrentLine = args;
|
||||
}
|
||||
|
||||
[Statement("!eval", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.VeryHigh, ExecuteInSearchLabelMode = true)]
|
||||
public void Evaluate(string args)
|
||||
{
|
||||
RuntimeInfo.CurrentLine = args.FromSaveString();
|
||||
}
|
||||
|
||||
[Statement("<", SearchMode.StartOfLine, SpaceAround.None, Priority = Priority.VeryLow, IgnoreSyntaxHighlighting = true)]
|
||||
public void DefineVariable(string args)
|
||||
{
|
||||
string[] parts = args.Split('=');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
string key = parts[0].Replace("<", "").Trim();
|
||||
if (RuntimeInfo.Variables.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.Variables[key] = parts[1].Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Variables.Add(key, parts[1].Trim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid syntax");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[StaticStatement(ExecuteInSearchLabelMode = true)]
|
||||
public void ReadVariable()
|
||||
{
|
||||
if (!RuntimeInfo.CurrentLine.Contains('>'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> variable in RuntimeInfo.Variables)
|
||||
{
|
||||
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using YesNt.Interpreter.Attributes;
|
||||
using YesNt.Interpreter.Enums;
|
||||
using YesNt.Interpreter.Utilities;
|
||||
|
||||
namespace YesNt.Interpreter.Statements
|
||||
{
|
||||
internal class CodeFlowStatements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("jmp", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)]
|
||||
public void Jump(string args)
|
||||
{
|
||||
string key = args.Trim();
|
||||
|
||||
if (RuntimeInfo.LabelStack.Count == 0 || RuntimeInfo.LabelStack.Peek() != RuntimeInfo.LineNumber)
|
||||
{
|
||||
RuntimeInfo.LabelStack.Push(RuntimeInfo.LineNumber);
|
||||
}
|
||||
|
||||
if (RuntimeInfo.Labels.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.LineNumber = RuntimeInfo.Labels[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.SearchLabel = key;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("jif", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)]
|
||||
public void JumpIf(string args)
|
||||
{
|
||||
string[] parts = args.Split('|');
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid syntax", true);
|
||||
return;
|
||||
}
|
||||
|
||||
string key = parts[0].Trim();
|
||||
string condition = parts[1].Trim();
|
||||
|
||||
bool? result = Evaluator.EvaluateCondition(condition);
|
||||
|
||||
if (result != true)
|
||||
{
|
||||
if (result is null)
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid operation", true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuntimeInfo.LabelStack.Count == 0 || RuntimeInfo.LabelStack.Peek() != RuntimeInfo.LineNumber)
|
||||
{
|
||||
RuntimeInfo.LabelStack.Push(RuntimeInfo.LineNumber);
|
||||
}
|
||||
|
||||
if (RuntimeInfo.Labels.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.LineNumber = RuntimeInfo.Labels[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.SearchLabel = key;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("lbl", SearchMode.StartOfLine, SpaceAround.End, ExecuteInSearchLabelMode = true)]
|
||||
public void FindLabel(string args)
|
||||
{
|
||||
string key = args.Trim();
|
||||
if (RuntimeInfo.Labels.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.Labels[key] = RuntimeInfo.LineNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Labels.Add(key, RuntimeInfo.LineNumber);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(RuntimeInfo.SearchLabel) && RuntimeInfo.SearchLabel == key)
|
||||
{
|
||||
RuntimeInfo.SearchLabel = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("ret", SearchMode.Exact, SpaceAround.None)]
|
||||
public void Return(string _)
|
||||
{
|
||||
if (RuntimeInfo.LabelStack.Count > 0)
|
||||
{
|
||||
RuntimeInfo.LineNumber = RuntimeInfo.LabelStack.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Exit("No label in stack", true);
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("end", SearchMode.Exact, SpaceAround.None)]
|
||||
public void End(string _)
|
||||
{
|
||||
RuntimeInfo.Exit("Planned termination by code", false);
|
||||
}
|
||||
|
||||
[Statement("trm", SearchMode.Exact, SpaceAround.None)]
|
||||
public void Terminate(string _)
|
||||
{
|
||||
RuntimeInfo.Exit("Planned termination by code. Canceling all tasks", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
|
||||
using YesNt.Interpreter.Attributes;
|
||||
using YesNt.Interpreter.Enums;
|
||||
using YesNt.Interpreter.Utilities;
|
||||
|
||||
namespace YesNt.Interpreter.Statements
|
||||
{
|
||||
internal class ConsoleStatements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("cwl", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)]
|
||||
public void WriteLine(string args)
|
||||
{
|
||||
RuntimeInfo.WriteLine(args);
|
||||
}
|
||||
|
||||
[Statement("cw", SearchMode.StartOfLine, SpaceAround.End, Priority = Priority.VeryLow)]
|
||||
public void Write(string args)
|
||||
{
|
||||
RuntimeInfo.Write(args);
|
||||
}
|
||||
|
||||
[Statement("%crl", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
||||
public void ReadLine(string args)
|
||||
{
|
||||
args += " ";
|
||||
while (args.Contains("%crl "))
|
||||
{
|
||||
string input = Console.ReadLine();
|
||||
if (input is null)
|
||||
{
|
||||
RuntimeInfo.Exit("Terminated by external process", true);
|
||||
return;
|
||||
}
|
||||
args = args.ReplaceFirstOccurrence("%crl ", input.ToSaveString() + " ");
|
||||
}
|
||||
RuntimeInfo.CurrentLine = args.TrimEnd();
|
||||
}
|
||||
|
||||
[Statement("%cr", SearchMode.Contains, SpaceAround.End, KeepStatementInArgs = true, Priority = Priority.Highest)]
|
||||
public void ReadKey(string args)
|
||||
{
|
||||
args += " ";
|
||||
while (args.Contains("%cr "))
|
||||
{
|
||||
string input = ConsoleExtentions.ReadKey(RuntimeInfo).ToString();
|
||||
args = args.ReplaceFirstOccurrence("%cr ", input.ToSaveString() + " ");
|
||||
}
|
||||
RuntimeInfo.CurrentLine = args.TrimEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using YesNt.Interpreter.Attributes;
|
||||
using YesNt.Interpreter.Enums;
|
||||
using YesNt.Interpreter.Utilities;
|
||||
|
||||
namespace YesNt.Interpreter.Statements
|
||||
{
|
||||
internal class ProcessingStatements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("!calc", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.High, ExecuteInSearchLabelMode = true)]
|
||||
public void Calculate(string args)
|
||||
{
|
||||
MatchCollection matches = Regex.Matches(args, @"((\)?)+(\(?)+[0-9]+(((\s?)+(\)?)(\s?)+\+(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\-(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\*(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\/(\s?)+(\(?)+(\s?)+)|[,.])(?=[0-9])+)+[0-9]+(\)?)+");
|
||||
|
||||
for (int i = 0; i < matches.Count; i++)
|
||||
{
|
||||
string res = Evaluator.Calculate(matches[i].Value);
|
||||
if (res is null)
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid operation", true);
|
||||
return;
|
||||
}
|
||||
args = args.Replace(matches[0].Value, res);
|
||||
}
|
||||
|
||||
RuntimeInfo.CurrentLine = args;
|
||||
}
|
||||
|
||||
[Statement("!eval", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.VeryHigh)]
|
||||
public void Evaluate(string args)
|
||||
{
|
||||
RuntimeInfo.CurrentLine = args.FromSaveString();
|
||||
}
|
||||
|
||||
[Statement("!task", SearchMode.EndOfLine, SpaceAround.Start, Priority = Priority.VeryHigh)]
|
||||
public void RunTask(string line)
|
||||
{
|
||||
int lineNumer = RuntimeInfo.LineNumber;
|
||||
List<string> lines = RuntimeInfo.Lines.GetRange(0, RuntimeInfo.Lines.Count);
|
||||
lines[lineNumer] = line;
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
YesNtInterpreter interpreter = new YesNtInterpreter();
|
||||
interpreter.Initialize();
|
||||
interpreter.Execute(lines, lineNumer, RuntimeInfo);
|
||||
});
|
||||
|
||||
RuntimeInfo.CurrentLine = string.Empty;
|
||||
}
|
||||
|
||||
[Statement("slp", SearchMode.StartOfLine, SpaceAround.End)]
|
||||
public void Sleep(string args)
|
||||
{
|
||||
_ = int.TryParse(args, out int millisecondsTimeout);
|
||||
ConsoleExtentions.Sleep(millisecondsTimeout, RuntimeInfo);
|
||||
}
|
||||
|
||||
[Statement("imp", SearchMode.StartOfLine, SpaceAround.End)]
|
||||
public void Import(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Path.GetExtension(path)))
|
||||
{
|
||||
path = Path.ChangeExtension(path, "ynt");
|
||||
}
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
RuntimeInfo.Lines.RemoveAt(0);
|
||||
RuntimeInfo.Lines.InsertRange(RuntimeInfo.LineNumber, File.ReadAllLines(path));
|
||||
RuntimeInfo.LineNumber--;
|
||||
}
|
||||
catch
|
||||
{
|
||||
RuntimeInfo.Exit($"Could not load file {path}", true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Exit($"Could not find file {path}", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using YesNt.Interpreter.Attributes;
|
||||
using YesNt.Interpreter.Enums;
|
||||
|
||||
namespace YesNt.Interpreter.Statements
|
||||
{
|
||||
internal class VariableStatements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("<", SearchMode.StartOfLine, SpaceAround.None, Priority = Priority.VeryLow, IgnoreSyntaxHighlighting = true)]
|
||||
public void DefineVariable(string args)
|
||||
{
|
||||
string[] parts = args.Split('=');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
string key = parts[0].Replace("<", "").Trim();
|
||||
if (key.Contains(' '))
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid Syntax", true);
|
||||
}
|
||||
|
||||
if (RuntimeInfo.Variables.ContainsKey(key))
|
||||
{
|
||||
RuntimeInfo.Variables[key] = parts[1].Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Variables.Add(key, parts[1].Trim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Exit("Invalid syntax", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[StaticStatement(ExecuteInSearchLabelMode = true)]
|
||||
public void ReadVariable()
|
||||
{
|
||||
if (!RuntimeInfo.CurrentLine.Contains('>'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> variable in RuntimeInfo.Variables)
|
||||
{
|
||||
RuntimeInfo.CurrentLine = RuntimeInfo.CurrentLine.Replace($">{variable.Key}", variable.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace YesNt.Interpreter.Utilities
|
||||
{
|
||||
internal static class ConsoleExtentions
|
||||
{
|
||||
public static char ReadKey(RuntimeInformation runtimeInformation)
|
||||
{
|
||||
while (!runtimeInformation.Stop)
|
||||
{
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
return Console.ReadKey().KeyChar;
|
||||
}
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
|
||||
public static void Sleep(int millisecondsTimeout, RuntimeInformation runtimeInformation)
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
while (!runtimeInformation.Stop)
|
||||
{
|
||||
if (stopwatch.ElapsedMilliseconds > millisecondsTimeout)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,10 +77,6 @@ namespace YesNt.Interpreter.Utilities
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
((\)?)+(\(?)+[0-9]+(((\s?)+(\)?)(\s?)+\+(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\-(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\*(\s?)+(\(?)+(\s?)+|(\s?)+(\)?)(\s?)+\/(\s?)+(\(?)+(\s?)+)|[,.])(?=[0-9])+)+[0-9]+(\)?)+
|
||||
*/
|
||||
|
||||
public static string Calculate(string input, char op = '+')
|
||||
{
|
||||
if (input is null)
|
||||
|
||||
+44
-17
@@ -32,6 +32,7 @@ namespace YesNt.CodeEditor
|
||||
yesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput;
|
||||
yesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted;
|
||||
syntaxHighlighter = new(yesNtInterpreter.StatementInformation);
|
||||
Console.CancelKeyPress += Console_CancelKeyPress;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
@@ -230,19 +231,32 @@ namespace YesNt.CodeEditor
|
||||
case "run":
|
||||
if (Save(input, true))
|
||||
{
|
||||
mode = Mode.Debug;
|
||||
Console.Clear();
|
||||
yesNtInterpreter.Execute(currentPath);
|
||||
while (Console.KeyAvailable)
|
||||
{
|
||||
Console.ReadKey(true);
|
||||
}
|
||||
Console.ReadKey();
|
||||
WriteStatus(string.Empty);
|
||||
mode = Mode.Command;
|
||||
}
|
||||
break;
|
||||
|
||||
case "debug":
|
||||
if (Save(input, true))
|
||||
{
|
||||
mode = Mode.Debug;
|
||||
Console.Clear();
|
||||
yesNtInterpreter.Execute(currentPath, true);
|
||||
while (Console.KeyAvailable)
|
||||
{
|
||||
Console.ReadKey(true);
|
||||
}
|
||||
Console.ReadKey();
|
||||
WriteStatus(string.Empty);
|
||||
mode = Mode.Command;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -257,12 +271,6 @@ namespace YesNt.CodeEditor
|
||||
break;
|
||||
}
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
WriteStatus("File does not exist!");
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Load(path);
|
||||
@@ -277,15 +285,13 @@ namespace YesNt.CodeEditor
|
||||
break;
|
||||
|
||||
case "new":
|
||||
if (Save(input, false))
|
||||
{
|
||||
lineOffset = 0;
|
||||
cursorPosition.X = 0;
|
||||
cursorPosition.Y = 0;
|
||||
currentPath = string.Empty;
|
||||
lines.Clear();
|
||||
WriteStatus(string.Empty);
|
||||
}
|
||||
|
||||
lineOffset = 0;
|
||||
cursorPosition.X = 0;
|
||||
cursorPosition.Y = 0;
|
||||
currentPath = string.Empty;
|
||||
lines.Clear();
|
||||
WriteStatus(string.Empty);
|
||||
break;
|
||||
|
||||
case "exit":
|
||||
@@ -302,6 +308,11 @@ namespace YesNt.CodeEditor
|
||||
|
||||
private bool Load(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Path.GetExtension(path)))
|
||||
{
|
||||
path = Path.ChangeExtension(path, "ynt");
|
||||
}
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
WriteStatus("File does not exist!");
|
||||
@@ -321,7 +332,6 @@ namespace YesNt.CodeEditor
|
||||
private bool Save(string input, bool loadIfExists)
|
||||
{
|
||||
string text = "";
|
||||
string path = "";
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
@@ -329,6 +339,7 @@ namespace YesNt.CodeEditor
|
||||
}
|
||||
text = text.TrimEnd('\n');
|
||||
|
||||
string path;
|
||||
if (input.Split(' ').Length == 2)
|
||||
{
|
||||
path = input.Split(' ')[1];
|
||||
@@ -361,6 +372,11 @@ namespace YesNt.CodeEditor
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Path.GetExtension(path)))
|
||||
{
|
||||
path = Path.ChangeExtension(path, "ynt");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllText(path, text);
|
||||
@@ -404,6 +420,16 @@ namespace YesNt.CodeEditor
|
||||
}
|
||||
debugOutput.Clear();
|
||||
}
|
||||
|
||||
private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
if (mode == Mode.Debug)
|
||||
{
|
||||
yesNtInterpreter.Stop();
|
||||
mode = Mode.Command;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class Point
|
||||
@@ -421,6 +447,7 @@ namespace YesNt.CodeEditor
|
||||
internal enum Mode
|
||||
{
|
||||
Edit,
|
||||
Command
|
||||
Command,
|
||||
Debug
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace YesNt.CodeEditor
|
||||
namespace YesNt.CodeEditor
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
@@ -8,7 +6,6 @@ namespace YesNt.CodeEditor
|
||||
{
|
||||
TextEditor textEditor;
|
||||
|
||||
Console.CancelKeyPress += Console_CancelKeyPress;
|
||||
if (args.Length > 0)
|
||||
{
|
||||
textEditor = new TextEditor(args[0]);
|
||||
@@ -20,10 +17,5 @@ namespace YesNt.CodeEditor
|
||||
|
||||
textEditor.Run();
|
||||
}
|
||||
|
||||
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user