using Convention.RScript.Parser; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Convention.RScript { public class RScriptEngine { private ExpressionParser parser; private RScriptContext context; private IEnumerable SplitScript(string script) { StringBuilder builder = new(); List statements = new(); void PushBuilder() { if (builder.Length > 0) { statements.Add(builder.ToString().Trim()); builder.Clear(); } } var lines = script.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++) { string line = lines[lineIndex]; for (int i = 0, e = line.Length; i < e; i++) { char c = line[i]; if (c == ';') { PushBuilder(); } else if (c == '/' && i + 1 < e) { // Skip single-line comment if (script[i + 1] == '/') { while (i < script.Length && script[i] != '\n') i++; } // Skip multi-line comment else if (script[i + 1] == '*') { i += 2; while (i + 1 < script.Length && !(script[i] == '*' && script[i + 1] == '/')) i++; i++; } else { builder.Append(c); } } else if (c == '#') { // Skip single-line comment while (i < script.Length && script[i] != '\n') i++; } else if (c == '\"') { for (i++; i < e; i++) { builder.Append(script[i]); if (script[i] == '\"') { break; } else if (script[i] == '\\') { i++; if (i < e) builder.Append(script[i]); else throw new RScriptCompileException("Invalid escape sequence in string literal", lineIndex, i); } } } else if (c == '{' || c == '}') { PushBuilder(); statements.Add(c.ToString()); } else if (string.Compare("namespace", 0, script, i, "namespace".Length) == 0) { builder.Append("namespace"); i += "namespace".Length; if (i >= e) throw new RScriptCompileException("Invalid namespace declaration", lineIndex, i); Regex regex = new(@"^\s*\([a-zA-Z_][a-zA-Z0-9_]*\)"); var match = regex.Match(script, i); if (match.Success) { builder.Append(match.Value); PushBuilder(); i += match.Length; } else { throw new RScriptCompileException("Invalid namespace declaration", lineIndex, i); } // 前面的操作中已经完成位移, 此处是抵消循环中的i++ i -= 1; } else { builder.Append(c); } } } if (builder.Length > 0) { PushBuilder(); } return statements.Where(s => !string.IsNullOrWhiteSpace(s)); } public Dictionary Run(string script, RScriptImportClass import = null, RScriptVariables variables = null) { parser = new(new()); context = new(SplitScript(script).ToArray(), import, variables); foreach (var type in context.Import) parser.context.Imports.AddType(type); context.Run(parser); return context.GetCurrentVariables(); } public IEnumerator RunAsync(string script, RScriptImportClass import = null, RScriptVariables variables = null) { parser = new(new()); context = new(SplitScript(script).ToArray(), import, variables); foreach (var type in context.Import) parser.context.Imports.AddType(type); return context.RunAsync(parser); } } }