123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- using Island.StandardLib;
- using Island.StandardLib.Math;
- using System;
- using System.Collections.Generic;
- namespace EXTS
- {
- public class EXTSEngine
- {
- internal static EXTSEngine CompilingEngine;
- public const string ValError = "err";
- public const string ValDefault = "non";
- public Dictionary<string, EValue> stdval;
- public Dictionary<string, FuncStatement> funcs;
- public Dictionary<string, FuncStatement> funcptrs;
- public BodyFuncStatement BodyStatement;
- public EXTSEngine()
- {
- stdval = new Dictionary<string, EValue>();
- funcs = new Dictionary<string, FuncStatement>();
- BodyStatement = new BodyFuncStatement(new Statement[0]);
- }
- public T AddStatement<T>(T statement) where T : Statement
- {
- BodyStatement.statements.Add(statement);
- return statement;
- }
- public FuncStatement AddStatement(string name, FuncStatement statement)
- {
- funcs.Add(name, statement);
- return statement;
- }
- internal Stack<string> func_invoke_stack;
- void CheckStackSafe()
- {
- if (func_invoke_stack.Count > 256)
- {
- Console.WriteLine("\n-------------------- 运行时错误 --------------------");
- Console.WriteLine("当前堆栈深度已超过堆栈的最大允许值为 256 ,程序中存在太多未回收的函数调用。请检查是否存在无限循环递归。");
- Console.WriteLine("堆栈列表:");
- Console.WriteLine(StkName(func_invoke_stack, true, " -> "));
- throw new RuntimeException("当前堆栈深度已超过堆栈的最大允许值为 256 ,程序中存在太多函数调用。请检查是否存在无限循环递归。");
- }
- }
- public EValue RunFuncPtr(string funcptr, EValue[] parameters)
- {
- if (!funcptrs.ContainsKey(funcptr))
- throw new RuntimeException("funcptr not founded.");
- FuncStatement fs = funcptrs[funcptr];
- fs.runfunc = true;
- func_invoke_stack.Push("{ AnonymousFunction }");
- CheckStackSafe();
- EValue ret = fs.Eval(parameters);
- func_invoke_stack.Pop();
- fs.runfunc = false;
- return ret;
- }
- public EValue RunFuncBase(string funcName, EValue[] parameters)
- {
- if (funcName.Contains(":"))
- {
- string val = funcName.Split(':')[0];
- string method = funcName.Split(':')[1];
- EValue value = StatementList.runningStatement[val];
- if (!value.Defined) throw new RuntimeException($"variable {val} not defined.");
- return value.Instance.PassCall(method, parameters);
- }
- switch (funcName)
- {
- case "Number":
- {
- if (parameters.Length == 0)
- return new EValue(new ENumber(0));
- else if (parameters.Length == 1)
- {
- ENumber n = parameters[0].As<ENumber>();
- if (n == null) throw new RuntimeException("Only can init CLASS with CLASS.");
- return new EValue(new ENumber(n.Value));
- }
- throw new RuntimeException("Number init usage error.");
- }
- case "Vec3":
- {
- if (parameters.Length == 0)
- return new EValue(new EVec3(new Vector3(0, 0, 0)));
- else if (parameters.Length == 1)
- {
- EVec3 n = parameters[0].As<EVec3>();
- if (n == null) throw new RuntimeException("Only can init CLASS with CLASS.");
- return new EValue(new EVec3(n.Value));
- }
- else if (parameters.Length == 3)
- {
- ENumber[] xyz = parameters.Do((val) => val.As<ENumber>());
- if (xyz.Contain(null)) throw new RuntimeException("[Vec3 x,y,z] Request Number parameters");
- }
- throw new RuntimeException("Vec3 init usage error.");
- }
- case "String":
- {
- if (parameters.Length == 0)
- return new EValue(new EString(""));
- else if (parameters.Length == 1)
- {
- EString n = parameters[0].As<EString>();
- if (n == null) throw new RuntimeException("Only can init CLASS with CLASS.");
- return new EValue(new EString(n.Value));
- }
- throw new RuntimeException("Vec3 init usage error.");
- }
- case "static":
- {
- if (parameters.Length == 1)
- {
- EString v = parameters[0].As<EString>();
- if (v == null) throw new RuntimeException("static varname request String class.");
- return stdval.Get(v.Value, new EValue());
- }
- else if (parameters.Length == 2)
- {
- EString v = parameters[0].As<EString>();
- if (v == null) throw new RuntimeException("static varname request String class.");
- stdval.Set(v.Value, parameters[1]);
- return parameters[1];
- }
- else throw new RuntimeException("static Usage Error.");
- }
- case "callfuncptr":
- {
- if (parameters.Length == 0) throw new RuntimeException("callfuncptr request a parameters.");
- EString v = parameters[0].As<EString>();
- if (v == null) throw new RuntimeException("callfuncptr usage error.");
- return RunFuncPtr(v.Value, parameters.Sub(1, parameters.Length));
- }
- case "stackinfo":
- {
- return new EValue(new EString(StkName(func_invoke_stack, true, " -> ")));
- }
- default:
- {
- FuncStatement fs = funcs.Get(funcName);
- if (fs == null) throw new RuntimeException($"Func {funcName} Not founded");
- func_invoke_stack.Push(funcName);
- CheckStackSafe();
- EValue ret = fs.Eval(parameters);
- func_invoke_stack.Pop();
- return ret;
- }
- }
- }
- string compilingCode;
- int compilingPos;
- const char EOF = (char)0;
- bool InList(char ch, char[] add)
- {
- for (int i = 0; i < add.Length; i++)
- if (ch == add[i]) return true;
- return false;
- }
- bool ChBlank(char ch)
- {
- if (ch == ' ' || ch == '\t' || ch == '\n') return true;
- else return false;
- }
- bool ChBlankTEOFA(char ch, char[] add)
- {
- if (ch == ' ' || ch == '\t' || ch == '\n' || ch == EOF || ch == ']') return true;
- return InList(ch, add);
- }
- char Peek()
- {
- if (compilingPos < compilingCode.Length)
- return compilingCode[compilingPos++];
- else
- {
- compilingPos++;
- return EOF;
- }
- }
- const string symallowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
- bool SymAllowed(char c, bool loc)
- {
- if (loc && (c == '.' || c == ':')) return true;
- for (int i = 0; i < symallowed.Length; i++)
- if (c == symallowed[i]) return true;
- return false;
- }
- /// <summary>
- /// 读取当前位置的字符,直到遇到空白字符和 excludelist 中的字符
- /// </summary>
- /// <param name="excludelist">被识别为空白字符的附加字符</param>
- /// <returns></returns>
- string PeekToBlank(params char[] excludelist)
- {
- string str = "";
- char ch;
- while (!ChBlankTEOFA(ch = Peek(), excludelist)) str += ch;
- compilingPos--;
- return str;
- }
- /// <summary>
- /// 读取当前位置的字符,直到遇到空白字符和 excludelist 中的字符,只允许字母数字和下划线输入
- /// </summary>
- /// <param name="excludelist">被识别为空白字符的附加字符</param>
- /// <returns></returns>
- string PeekToBlankSym(params char[] excludelist)
- {
- string str = "";
- char ch;
- while (!ChBlankTEOFA(ch = Peek(), excludelist))
- {
- if (!SymAllowed(ch, false)) throw new SyntaxException("在符号定义中,不允许出现字符 " + ch, compilingPos);
- str += ch;
- }
- compilingPos--;
- return str;
- }
- string PeekToBlankLocSym(params char[] excludelist)
- {
- string str = "";
- char ch;
- while (!ChBlankTEOFA(ch = Peek(), excludelist))
- {
- if (!SymAllowed(ch, true)) throw new SyntaxException("在符号定义中,不允许出现字符 " + ch, compilingPos);
- str += ch;
- }
- compilingPos--;
- return str;
- }
- /// <summary>
- /// 跳过空白字符和 includelist 中的字符,转到下一个字的前一个位置
- /// </summary>
- /// <param name="includelist">被识别为空白字符的附加字符</param>
- void PeekToWord(params char[] includelist)
- {
- char ch;
- while (ChBlank(ch = Peek()) || InList(ch, includelist)) ;
- compilingPos--;
- }
- string PeekString()
- {
- string str = "";
- char ch;
- while (true)
- {
- ch = Peek();
- if (ch == '\\')
- {
- char ct = Peek();
- switch (ct)
- {
- case 'n': str += '\n'; break;
- case 't': str += '\t'; break;
- case '\"': str += '\"'; break;
- case '\\': str += '\\'; break;
- default: throw new SyntaxException("未识别的转义符。", compilingPos);
- }
- }
- if (ch == EOF) throw new SyntaxException("字符串直到文件结尾都未结束,请检查引号是否完整。", compilingPos);
- if (ch == '\"')
- {
- break;
- }
- str += ch;
- }
- return str;
- }
- ImmediateStatement CompileImmediateStatementF()
- {
- string valstr = PeekToBlank(';');
- ImmediateStatement statement = new ImmediateStatement(valstr);
- PeekToWord();
- return statement;
- }
- ImmediateStatement CompileImmediateStatementS()
- {
- ImmediateStatement statement = new ImmediateStatement(PeekString());
- PeekToWord();
- return statement;
- }
- GetValStatement CompileGetValStatement()
- {
- GetValStatement statement = new GetValStatement(currentfunc.Peek(), PeekToBlankSym(';'));
- PeekToWord();
- return statement;
- }
- CallFuncStatement CompileCallFuncStatement()
- {
- List<Statement> pmts = new List<Statement>();
- PeekToWord();
- string calName = PeekToBlankLocSym('[');
-
- if (calName.Length > 0)
- {
- if (calName[0] == '.')
- {
- calName = calName.Substring(1);
- func_compile_stack.Push(calName);
- calName = StkName(func_compile_stack, true);
- func_compile_stack.Pop();
- }
- }
-
- PeekToWord();
- while (true)
- {
- switch (Peek())
- {
- case '[': pmts.Add(CompileCallFuncStatement()); break;
- case '$': pmts.Add(CompileImmediateStatementF()); break;
- case '\"': pmts.Add(CompileImmediateStatementS()); break;
- case ':':
- {
- compilingPos--;
- pmts.Add(CompileFuncStatement(currentfunc.Peek() as FuncStatement, true));
- break;
- }
- case ']': return new CallFuncStatement(calName, pmts.ToArray());
- case ';': throw new SyntaxException("在函数调用中,意外的语句结束。", compilingPos);
- case EOF: throw new SyntaxException("函数调用直到文件结尾都未结束,请检查方括号是否匹配。", compilingPos);
- default: compilingPos--; pmts.Add(CompileGetValStatement()); break;
- }
- PeekToWord();
- }
- }
- SetValStatement CompileSetValStatement(string name)
- {
- PeekToWord();
- Statement valst;
- switch (Peek())
- {
- case '[': valst = CompileCallFuncStatement(); break;
- case '$': valst = CompileImmediateStatementF(); break;
- case '\"': valst = CompileImmediateStatementS(); break;
- case ']': throw new SyntaxException("在赋值语句中,意外的符号 ]。", compilingPos);
- case ';': throw new SyntaxException("在赋值语句中,意外的语句结束。", compilingPos);
- case EOF: throw new SyntaxException("赋值语句直到文件结尾都未结束,请检查方括号是否匹配。", compilingPos);
- default: compilingPos--; valst = CompileGetValStatement(); break;
- }
- PeekToWord();
- char ch = Peek();
- if (ch == ';') return new SetValStatement(currentfunc.Peek(), name, valst);
- throw new SyntaxException("赋值语句结束后仍然出现语句,请检查是否缺少分号。", compilingPos);
- }
- string StkName(Stack<string> stk, bool reverse, string link = ".")
- {
- string b = "";
- List<string> r = new List<string>();
- foreach (string st in stk)
- r.Add(st);
- if (reverse) r.Reverse();
- for (int i = 0; i < r.Count; i++)
- b += r[i] + link;
- if (b.Length != 0)
- b = b.Substring(0, b.Length - link.Length);
- return b;
- }
- Statement CompileStatement()
- {
- PeekToWord();
- char ch = Peek();
- switch (ch)
- {
- case EOF: throw new SyntaxException("语句直到文件结尾都未结束。", compilingPos);
- case ';': throw new SyntaxException("不可分析的语句结尾。", compilingPos);
- case '[': return CompileCallFuncStatement();
- case '$': return CompileImmediateStatementF();
- case '\"': return CompileImmediateStatementS();
- default:
- {
- string name = ch + PeekToBlankSym('=', ';');
- PeekToWord();
- char p = Peek();
- if (p == EOF) throw new SyntaxException("不可分析的文件结尾。", compilingPos);
- else if (p == '=') return CompileSetValStatement(name);
- else
- {
- compilingPos--;
- return new GetValStatement(currentfunc.Peek(), name);
- }
- }
- }
- }
- FuncStatement CompileFuncStatement(FuncStatement parent, bool isAnonymousFunc)
- {
- string funcname = PeekToBlankSym(':', '{');
- FuncStatement func = new FuncStatement();
- func.runfunc = !isAnonymousFunc;
- func.parentVarlst = parent;
- currentfunc.Push(func);
- func_compile_stack.Push(funcname);
- string fullfuncname = StkName(func_compile_stack, true);
- func.name = fullfuncname;
- PeekToWord();
- char t = Peek();
- if (t == ':')
- {
- int i = 0;
- while (true)
- {
- PeekToWord();
- char p = Peek();
- if (p == EOF) throw new SyntaxException("函数的参数列表直到文件结尾都未结束,请检查函数 " + funcname + " 的定义。", compilingPos);
- if (p == '{') break;
- compilingPos--;
- string varname = PeekToBlankSym();
- func.AddStatement(new SetValStatement(func, varname, new GetValStatement(func, "pmt" + i)));
- i++;
- }
- PeekToWord();
- }
- else if (t == '{')
- PeekToWord();
- else throw new SyntaxException("错误的函数表达式形式。", compilingPos);
- char ch;
- while (true)
- {
- PeekToWord();
- ch = Peek();
- switch (ch)
- {
- case EOF:
- throw new SyntaxException("函数 " + funcname + " 直到文件结尾都未结束,请检查大括号是否匹配。", compilingPos);
- case '}':
- func_compile_stack.Pop();
- currentfunc.Pop();
- if (!isAnonymousFunc)
- {
- if (funcs.ContainsKey(fullfuncname))
- throw new SyntaxException("有一个重复的函数 " + fullfuncname + " 。是否使用重载函数?", compilingPos);
- funcs.Add(fullfuncname, func);
- }
- return func;
- case '[':
- func.AddStatement(CompileCallFuncStatement());
- PeekToWord();
- if (Peek() != ';') throw new SyntaxException("函数调用结束后仍然出现语句,请检查是否缺少分号。", compilingPos);
- break;
- default:
- {
- string name = ch + PeekToBlankSym('=', ';');
- PeekToWord();
- char p = Peek();
- if (p == EOF) throw new SyntaxException("不可分析的文件结尾。", compilingPos);
- else if (p == '=') func.AddStatement(CompileSetValStatement(name));
- else
- {
- compilingPos--;
- if (name == "func")
- {
- if (isAnonymousFunc)
- throw new SyntaxException("当前EXTS版本中,在一个匿名函数中定义一个非匿名函数是没有意义的,因为无法确定这个函数的访问标识符,不排除以后的版本中xc会实现。", compilingPos);
- CompileFuncStatement(func, isAnonymousFunc);
- }
- else if (name == "return")
- {
- PeekToWord();
- char e = Peek();
- if (e == ';')
- {
- func.AddStatement(new ReturnStatement());
- }
- else
- {
- compilingPos--;
- func.AddStatement(new SetValStatement(func, "return", CompileStatement()));
- func.AddStatement(new ReturnStatement());
- }
- }
- }
- }
- break;
- }
- }
- }
- Stack<StatementList> currentfunc;
- Stack<string> func_compile_stack;
- public void Compile(string str)
- {
- str = str.Replace("\0", "").Replace("\r", "");
- CompilingEngine = this;
- compilingCode = str;
- compilingPos = 0;
- currentfunc = new Stack<StatementList>();
- currentfunc.Push(BodyStatement);
- func_compile_stack = new Stack<string>();
- char ch;
- while (true)
- {
- PeekToWord();
- ch = Peek();
- switch (ch)
- {
- case EOF:
- CompilingEngine = null;
- return;
- case '[':
- currentfunc.Peek().AddStatement(CompileCallFuncStatement());
- PeekToWord();
- if (Peek() != ';') throw new SyntaxException("函数调用结束后仍然出现语句,请检查是否缺少分号。", compilingPos);
- break;
- default:
- {
- string name = ch + PeekToBlankSym('=');
- PeekToWord();
- char p = Peek();
- if (p == EOF) throw new SyntaxException("不可分析的文件结尾。", compilingPos);
- else if (p == '=') currentfunc.Peek().AddStatement(CompileSetValStatement(name));
- else
- {
- compilingPos--;
- if (name == "func")
- {
- CompileFuncStatement(null, false);
- }
- }
- }
- break;
- }
- }
- }
- public void Reset()
- {
- BodyStatement = new BodyFuncStatement();
- funcs = new Dictionary<string, FuncStatement>();
- funcptrs = new Dictionary<string, FuncStatement>();
- }
- public EValue Run(params KeyValuePair<string, EValue>[] pmts)
- {
- stdval.Clear();
- funcptrs = new Dictionary<string, FuncStatement>();
- func_invoke_stack = new Stack<string>();
- EValue val = BodyStatement.Eval(pmts);
- StatementList.runningStatement = null;
- return val;
- }
- }
- }
|