|
|
-
- using System.Globalization;
- using Smoll.Ex2;
- using Smoll.Ex4.Commands;
-
- namespace Smoll.Ex4 {
- class ScriptComponent : Component {
- string script;
- ScriptComponent(string filename) {
- script = filename;
- }
-
- static Dictionary<string, Commands.ICommand>? globalCommands;
- Dictionary<string, Commands.ICommand> localCommands;
-
- public override void Draw(Layer.DrawMode drawMode)
- {
- ICommand command;
- if(localCommands.TryGetValue("Draw", out command)) {
- List<IScriptable> stack = new List<IScriptable>();
- command.Perform(stack);
- }
- }
-
- public override void OnAttached()
- {
- localCommands = Compile(owner.layers.First().attachedEngine.GetModule<RaylibAssetManagerModule>().GetScript(script));
-
- ICommand command;
- if(localCommands.TryGetValue("OnAttached", out command)) {
- List<IScriptable> stack = new List<IScriptable>();
- command.Perform(stack);
- }
- }
-
- public override void Update(float deltaTimeSeconds)
- {
- ICommand command;
- if(localCommands.TryGetValue("Update", out command)) {
- List<IScriptable> stack = new List<IScriptable>();
- stack.Add(new Number(deltaTimeSeconds));
- command.Perform(stack);
- }
- }
-
- static void EnsureCommandsInitialized() {
- if(globalCommands != null) return;
- globalCommands = new Dictionary<string, Commands.ICommand>
- {
- { "+", new Commands.AddNumberCommand() },
- { "print", new Commands.PrintCommand() }
- };
- }
-
- struct SString {
- public bool isLiteral;
- public string value;
-
- public string ToString() {
- if(isLiteral) {
- return "<" + value + ">";
- } else {
- return "["+value+"]";
- }
- }
- }
-
- static List<SString> Tokenize(string str) {
- var l = new List<SString>();
-
- string current = "";
- bool inString = false;
-
- TextElementEnumerator graphemeEnum = StringInfo.GetTextElementEnumerator(str.Normalize());
- while (graphemeEnum.MoveNext())
- {
- string grapheme = graphemeEnum.GetTextElement();
- if(inString) {
- if(grapheme == "\"") {
- bool valid = graphemeEnum.MoveNext();
- if(!valid) {
- SString s;
- s.value = current;
- s.isLiteral = true;
- l.Add(s);
- break;
- }
- grapheme = graphemeEnum.GetTextElement();
- if(grapheme == "\"") current += "\"";
- else if(grapheme.Trim() == string.Empty) {
- SString s;
- s.value = current;
- s.isLiteral = true;
- l.Add(s);
- current = "";
- inString = false;
- } else if(grapheme == "/") {
- bool valid2 = graphemeEnum.MoveNext();
- if(!valid2) {
- throw new Exception("Found a / for a new line definition that didn't end");
- }
- grapheme = graphemeEnum.GetTextElement();
- if(grapheme == "\"") current += "\n";
- } else {
- throw new Exception("Found \" of a literal followed by things");
- }
- } else {
- current += grapheme;
- }
- } else if(grapheme.Trim() == string.Empty) {
- if(current != string.Empty) {
- SString s;
- s.value = current;
- s.isLiteral = false;
- l.Add(s);
- current = "";
- inString = false;
- }
- } else {
- if(grapheme == "\"" && current == string.Empty) {
- inString = true;
- } else if(grapheme == "\"" && current != string.Empty) {
- throw new Exception("Found \" in atom");
- } else {
- current += grapheme;
- }
- }
- }
-
- if(inString) {
- throw new Exception("Found unterminated string");
- }
-
- if(current != string.Empty) {
- SString s;
- s.value = current;
- s.isLiteral = false;
- l.Add(s);
- }
-
- return l;
- }
-
- static public Dictionary<string, Commands.ICommand> Compile(string code) {
- EnsureCommandsInitialized();
- Dictionary<string, Commands.ICommand> localCommands = new Dictionary<string, Commands.ICommand>();
- var lines = code.Split("\n", StringSplitOptions.RemoveEmptyEntries);
-
- foreach (var line in lines)
- {
- var executable = new List<ICommand>();
- var fullLine = Tokenize(line);
- if(fullLine.Count < 2) {
- throw new Exception("Functions need to start with a name and a --");
- }
- var name = fullLine.First().value;
- if(fullLine.First().isLiteral) {
- throw new Exception("Literals cannot be function names");
- }
- if(fullLine[1].isLiteral || fullLine[1].value != "--") {
- throw new Exception("Function body needs to start with --");
- }
- foreach(var elem in fullLine.Skip(2)) {
- if(elem.isLiteral) {
- executable.Add(new Commands.PushStringCommand(elem.value));
- continue;
- }
- {
- double attempt;
- if(Double.TryParse(elem.value, out attempt)) {
- executable.Add(new Commands.PushNumberCommand(attempt));
- continue;
- }
- }
- {
- ICommand command;
- if(!localCommands.TryGetValue(elem.value, out command)) {
- if(!globalCommands.TryGetValue(elem.value, out command)) {
- executable.Add(new Commands.PushAtomCommand(elem.value));
- continue;
- }
- }
- executable.Add(command);
- }
- }
- localCommands.Add(name, new CompositeCommand(executable));
- }
-
- return localCommands;
- }
- }
- }
|