├── .gitattributes ├── .gitignore ├── README.md ├── Script ├── Script.sln ├── Script │ ├── Lexer.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Script.csproj │ ├── ScriptAction.cs │ ├── ScriptClass.cs │ ├── ScriptCondition.cs │ ├── ScriptEngine.cs │ ├── ScriptException.cs │ ├── ScriptFunction.cs │ ├── ScriptMethod.cs │ ├── ScriptProperty.cs │ ├── ScriptScope.cs │ ├── ScriptType.cs │ ├── ScriptTypeCondition.cs │ ├── ScriptTypeFunction.cs │ ├── ScriptTypeMethod.cs │ ├── ScriptTypeProperty.cs │ ├── ScriptTypes.cs │ ├── ScriptVariable.cs │ ├── TokenDefinitions.cs │ └── Tokens.cs └── ScriptTest │ ├── ArithmeticInteger.cs │ ├── Cast.cs │ ├── Condition.cs │ ├── ConditionElse.cs │ ├── ConditionIfElse.cs │ ├── Debug.cs │ ├── Evaluate.cs │ ├── Execute.cs │ ├── ExecuteOverload.cs │ ├── Extend.cs │ ├── ForLoop.cs │ ├── Function.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Property.cs │ ├── RegexBasic.cs │ ├── ScriptTest.csproj │ ├── Trigger.cs │ └── Variable.cs └── ScriptDemo ├── ScriptDemo.sln └── ScriptDemo ├── App.xaml ├── App.xaml.cs ├── ApplicationInsights.config ├── Assets ├── LockScreenLogo.scale-200.png ├── SplashScreen.scale-200.png ├── Square150x150Logo.scale-200.png ├── Square44x44Logo.scale-200.png ├── Square44x44Logo.targetsize-24_altform-unplated.png ├── StoreLogo.png └── Wide310x150Logo.scale-200.png ├── MainPage.xaml ├── MainPage.xaml.cs ├── Package.appxmanifest ├── Properties ├── AssemblyInfo.cs └── Default.rd.xml ├── ScriptDemo.csproj └── project.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | 154 | # Windows Azure Build Output 155 | csx/ 156 | *.build.csdef 157 | 158 | # Windows Store app package directory 159 | AppPackages/ 160 | 161 | # Visual Studio cache files 162 | # files ending in .cache can be ignored 163 | *.[Cc]ache 164 | # but keep track of directories ending in .cache 165 | !*.[Cc]ache/ 166 | 167 | # Others 168 | ClientBin/ 169 | [Ss]tyle[Cc]op.* 170 | ~$* 171 | *~ 172 | *.dbmdl 173 | *.dbproj.schemaview 174 | *.pfx 175 | *.publishsettings 176 | node_modules/ 177 | orleans.codegen.cs 178 | 179 | # RIA/Silverlight projects 180 | Generated_Code/ 181 | 182 | # Backup & report files from converting an old project file 183 | # to a newer Visual Studio version. Backup files are not needed, 184 | # because we have git ;-) 185 | _UpgradeReport_Files/ 186 | Backup*/ 187 | UpgradeLog*.XML 188 | UpgradeLog*.htm 189 | 190 | # SQL Server files 191 | *.mdf 192 | *.ldf 193 | 194 | # Business Intelligence projects 195 | *.rdl.data 196 | *.bim.layout 197 | *.bim_*.settings 198 | 199 | # Microsoft Fakes 200 | FakesAssemblies/ 201 | 202 | # Node.js Tools for Visual Studio 203 | .ntvs_analysis.dat 204 | 205 | # Visual Studio 6 build log 206 | *.plg 207 | 208 | # Visual Studio 6 workspace options file 209 | *.opt 210 | 211 | # Visual Studio LightSwitch build output 212 | **/*.HTMLClient/GeneratedArtifacts 213 | **/*.DesktopClient/GeneratedArtifacts 214 | **/*.DesktopClient/ModelManifest.xml 215 | **/*.Server/GeneratedArtifacts 216 | **/*.Server/ModelManifest.xml 217 | _Pvt_Extensions 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Script 2 | 3 | A simple portable scripting engine for C#. Think Python syntax with JavaScript objects and strict typing. 4 | 5 | ## Documentation 6 | 7 | Please view the [wiki](https://github.com/Templarian/Script/wiki) for a comprehensive overview and code samples. 8 | 9 | ## Features 10 | 11 | * Written from the ground up for readability. 12 | * Intuitive C# syntax on intepreter and script side. 13 | * Comprehensive syntax errors and script errors. 14 | * Strict typing allows method overloading based on datatype. 15 | * Simple... `int`, `double`, `string`, `bool`, and `regex` [data types](https://github.com/Templarian/Script/wiki/Types). 16 | * Implicit conversions for all types `("foo1" = "foo" + 1)` 17 | 18 | 19 | ## Hello World 20 | 21 | ```csharp 22 | static void Main() 23 | { 24 | var engine = new ScriptEngine(); 25 | engine.AddAction("log", Log); 26 | engine.Execute("log('Hello World!')"); 27 | Console.In.Read(); 28 | } 29 | static void Log(string message) 30 | { 31 | Console.WriteLine(message); 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /Script/Script.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script", "Script\Script.csproj", "{E8C08C44-303E-4F2C-98CC-E22DBAC85C60}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptTest", "ScriptTest\ScriptTest.csproj", "{9E90A7D0-5268-4267-B607-01C6341299B4}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|ARM = Release|ARM 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|ARM.ActiveCfg = Debug|Any CPU 25 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|ARM.Build.0 = Debug|Any CPU 26 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x64.ActiveCfg = Debug|Any CPU 27 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x64.Build.0 = Debug|Any CPU 28 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x86.ActiveCfg = Debug|Any CPU 29 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x86.Build.0 = Debug|Any CPU 30 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|ARM.ActiveCfg = Release|Any CPU 33 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|ARM.Build.0 = Release|Any CPU 34 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x64.ActiveCfg = Release|Any CPU 35 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x64.Build.0 = Release|Any CPU 36 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x86.ActiveCfg = Release|Any CPU 37 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x86.Build.0 = Release|Any CPU 38 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|ARM.ActiveCfg = Debug|Any CPU 41 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|ARM.Build.0 = Debug|Any CPU 42 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|x64.ActiveCfg = Debug|Any CPU 43 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|x64.Build.0 = Debug|Any CPU 44 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|x86.ActiveCfg = Debug|Any CPU 45 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Debug|x86.Build.0 = Debug|Any CPU 46 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|ARM.ActiveCfg = Release|Any CPU 49 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|ARM.Build.0 = Release|Any CPU 50 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|x64.ActiveCfg = Release|Any CPU 51 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|x64.Build.0 = Release|Any CPU 52 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|x86.ActiveCfg = Release|Any CPU 53 | {9E90A7D0-5268-4267-B607-01C6341299B4}.Release|x86.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /Script/Script/Lexer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | 9 | namespace Script 10 | { 11 | public interface IMatcher 12 | { 13 | /// 14 | /// Return the number of characters that this "regex" or equivalent 15 | /// matches. 16 | /// 17 | /// The text to be matched 18 | /// The number of characters that matched 19 | int Match(string text); 20 | } 21 | 22 | internal sealed class RegexMatcher : IMatcher 23 | { 24 | private readonly Regex regex; 25 | public RegexMatcher(string regex) 26 | { 27 | this.regex = new Regex(string.Format("^{0}", regex)); 28 | } 29 | 30 | public int Match(string text) 31 | { 32 | var m = regex.Match(text); 33 | return m.Success ? m.Length : 0; 34 | } 35 | 36 | public override string ToString() 37 | { 38 | return regex.ToString(); 39 | } 40 | } 41 | 42 | public sealed class TokenDefinitionGroup 43 | { 44 | public TokenDefinitionGroup (string name, TokenDefinition[] tokenDefinitions) 45 | { 46 | this.Name = name; 47 | this.TokenDefinitions = tokenDefinitions; 48 | } 49 | public readonly string Name; 50 | public readonly TokenDefinition[] TokenDefinitions; 51 | } 52 | 53 | public sealed class TokenDefinition 54 | { 55 | public IMatcher Matcher; 56 | public readonly Tokens Token; 57 | 58 | public TokenDefinition(string regex, Tokens token) 59 | { 60 | this.Matcher = new RegexMatcher(regex); 61 | this.Token = token; 62 | } 63 | } 64 | 65 | public sealed class History 66 | { 67 | public History(int lineNumber, int position, string lineRemaining) 68 | { 69 | LineNumber = lineNumber; 70 | Position = position; 71 | LineRemaining = lineRemaining; 72 | } 73 | public int LineNumber { get; set; } 74 | public int Position { get; set; } 75 | public string LineRemaining { get; set; } 76 | } 77 | 78 | public class Lexer : IDisposable 79 | { 80 | private readonly TextReader reader; 81 | private readonly List tokenDefinitionGroups; 82 | private string groupName; 83 | 84 | private string lineRemaining; 85 | private Action error; 86 | 87 | public Lexer(TextReader reader, List tokenDefinitionGroups, Action error) 88 | { 89 | this.reader = reader; 90 | this.tokenDefinitionGroups = tokenDefinitionGroups; 91 | this.error = error; 92 | this.groupName = tokenDefinitionGroups.First().Name; 93 | nextLine(); 94 | } 95 | 96 | private void nextLine() 97 | { 98 | do 99 | { 100 | lineRemaining = reader.ReadLine(); 101 | ++LineNumber; 102 | Position = -1; 103 | } while (lineRemaining != null && lineRemaining.Length == 0); 104 | } 105 | 106 | public void SkipBlock() 107 | { 108 | nextLine(); 109 | } 110 | 111 | public void Step(string groupName) 112 | { 113 | this.groupName = groupName; 114 | } 115 | 116 | private Stack Past = new Stack(); 117 | 118 | public bool Next() 119 | { 120 | return Next(false); 121 | } 122 | public bool Next(bool supressError) 123 | { 124 | Past.Push(new History(LineNumber, Position, lineRemaining)); 125 | 126 | if (lineRemaining == null) 127 | { 128 | return false; 129 | } 130 | else if (lineRemaining.Length == 0) // Return true while still empty somehow. 131 | { 132 | nextLine(); 133 | } 134 | 135 | if (Position == -1) 136 | { 137 | Token = Tokens.Block; 138 | Position = 0; 139 | return true; 140 | } 141 | 142 | foreach (var def in tokenDefinitionGroups.First(x => x.Name == this.groupName).TokenDefinitions) 143 | { 144 | var matched = def.Matcher.Match(lineRemaining); 145 | if (matched > 0) 146 | { 147 | Position += matched; 148 | Token = def.Token; 149 | TokenContents = lineRemaining.Substring(0, matched); 150 | lineRemaining = lineRemaining.Substring(matched); 151 | if (lineRemaining.Length == 0) // Return true while still empty somehow. 152 | { 153 | //nextLine(); 154 | } 155 | return true; 156 | } 157 | } 158 | if (!supressError) 159 | { 160 | error.DynamicInvoke(LineNumber, Position, lineRemaining); 161 | } 162 | return false; 163 | } 164 | 165 | public bool Prev() 166 | { 167 | var history = Past.Pop(); 168 | Position = history.Position; 169 | LineNumber = history.LineNumber; 170 | lineRemaining = history.LineRemaining; 171 | return true; 172 | } 173 | 174 | public string TokenContents { get; private set; } 175 | 176 | public Tokens Token { get; private set; } 177 | 178 | public int LineNumber { get; private set; } 179 | 180 | public int Position { get; private set; } 181 | 182 | public void Dispose() 183 | { 184 | reader.Dispose(); 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /Script/Script/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Script")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Script")] 14 | [assembly: AssemblyCopyright("Copyright © 2013")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en")] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /Script/Script/Script.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 11.0 6 | Debug 7 | AnyCPU 8 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60} 9 | Library 10 | Properties 11 | Script 12 | Script 13 | v4.5 14 | Profile78 15 | 512 16 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 68 | -------------------------------------------------------------------------------- /Script/Script/ScriptAction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptAction : ScriptMethod 10 | { 11 | 12 | public ScriptAction(string name, Delegate function) : base(name, function) 13 | { 14 | Name = name; 15 | Method = function; 16 | Types = new ScriptTypes[] { }; 17 | ReturnType = ScriptTypes.Void; 18 | } 19 | 20 | public ScriptAction(string name, Delegate function, ScriptTypes[] types) : base(name, function, types) 21 | { 22 | Name = name; 23 | Method = function; 24 | Types = types; 25 | ReturnType = ScriptTypes.Void; 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Script/Script/ScriptClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | 8 | namespace Script 9 | { 10 | public class ScriptClass 11 | { 12 | 13 | public string Name { get; set; } 14 | public Delegate Function { get; set; } 15 | 16 | internal Action Error; 17 | internal List Variables = new List(); 18 | internal List Properties = new List(); 19 | internal List Methods = new List(); 20 | 21 | public ScriptClass() 22 | { 23 | 24 | } 25 | 26 | public ScriptClass(string name) 27 | { 28 | Name = name; 29 | } 30 | 31 | public void SetVariable(string name, ScriptVariable value) 32 | { 33 | var property = Variables.FirstOrDefault(p => p.Name == name); 34 | if (property == null) 35 | { 36 | value.Name = name; 37 | Variables.Add(value); 38 | } 39 | else 40 | { 41 | if (property.Type == value.Type) 42 | { 43 | property.Value = value; 44 | } 45 | else 46 | { 47 | throw new ScriptException( 48 | message: String.Format("'{0}' requires a data type of {1}", 49 | name, 50 | value.Type), 51 | row: 0, 52 | column: 0 53 | ); 54 | } 55 | } 56 | } 57 | 58 | public ScriptVariable GetProperty(string name) 59 | { 60 | return Variables.Where(v => v.Name == name).FirstOrDefault(); 61 | } 62 | 63 | public void DeleteProperty(string name) 64 | { 65 | Variables.RemoveAll(property => property.Name == name); 66 | } 67 | 68 | public void AddProperty(string name, string value) 69 | { 70 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.String)); 71 | } 72 | 73 | public void AddProperty(string name, int value) 74 | { 75 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Integer)); 76 | } 77 | 78 | public void AddProperty(string name, double value) 79 | { 80 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 81 | } 82 | 83 | public void AddProperty(string name, bool value) 84 | { 85 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 86 | } 87 | 88 | public void AddProperty(string name, Regex value) 89 | { 90 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 91 | } 92 | 93 | public void AddProperty(string name, List value) 94 | { 95 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 96 | } 97 | 98 | public void AddProperty(string name, List value) 99 | { 100 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 101 | } 102 | 103 | public void AddProperty(string name, List value) 104 | { 105 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 106 | } 107 | 108 | public void AddProperty(string name, List value) 109 | { 110 | Properties.Add(new ScriptVariable(name, value, ScriptTypes.Double)); 111 | } 112 | 113 | private void AddProperty(string name, object value) 114 | { 115 | Properties.Add(new ScriptVariable(name, value)); 116 | } 117 | 118 | /// 119 | /// Add a user defined function to the script engine. 120 | /// 121 | /// Function name in the script. Example "dialog" 122 | /// A Func definition. 123 | public void AddFunction(string name, Func function) 124 | { 125 | ScriptTypes[] args = { }; 126 | var tr = ScriptType.ToEnum(typeof(TResult)); 127 | Methods.Add(new ScriptFunction(name, function, args, tr)); 128 | } 129 | 130 | public void AddFunction(string name, Func function) 131 | { 132 | var t1 = ScriptType.ToEnum(typeof(T1)); 133 | var tr = ScriptType.ToEnum(typeof(TResult)); 134 | ScriptTypes[] args = { t1 }; 135 | Methods.Add(new ScriptFunction(name, function, args, tr)); 136 | } 137 | 138 | public void AddFunction(string name, Func function) 139 | { 140 | var t1 = ScriptType.ToEnum(typeof(T1)); 141 | var t2 = ScriptType.ToEnum(typeof(T2)); 142 | var tr = ScriptType.ToEnum(typeof(TResult)); 143 | ScriptTypes[] args = { t1, t2 }; 144 | Methods.Add(new ScriptFunction(name, function, args, tr)); 145 | } 146 | 147 | /// 148 | /// Add an action with 0 arguments. Actions do not have a return type. 149 | /// 150 | /// The action's name in the script. 151 | /// Executed when action name is found and argument types match. 152 | public void AddAction(string name, Action action) 153 | { 154 | Methods.Add(new ScriptFunction(name, action)); 155 | } 156 | 157 | 158 | public void AddAction(string name, Action action) 159 | { 160 | var t1 = ScriptType.ToEnum(typeof(T1)); 161 | ScriptTypes[] args = { t1 }; 162 | Methods.Add(new ScriptFunction(name, action, args)); 163 | } 164 | 165 | 166 | public void AddAction(string name, Action action) 167 | { 168 | var t1 = ScriptType.ToEnum(typeof(T1)); 169 | var t2 = ScriptType.ToEnum(typeof(T2)); 170 | ScriptTypes[] args = { t1, t2 }; 171 | Methods.Add(new ScriptFunction(name, action, args)); 172 | } 173 | 174 | 175 | public void AddAction(string name, Action action) 176 | { 177 | var t1 = ScriptType.ToEnum(typeof(T1)); 178 | var t2 = ScriptType.ToEnum(typeof(T2)); 179 | var t3 = ScriptType.ToEnum(typeof(T3)); 180 | ScriptTypes[] args = { t1, t2, t3 }; 181 | Methods.Add(new ScriptFunction(name, action, args)); 182 | } 183 | 184 | /// 185 | /// Add a user defined function to the script engine. 186 | /// 187 | /// Function name in the script. Example "dialog" 188 | /// A Predicate definition. 189 | public void AddCondition(string name, Func condition) 190 | { 191 | var t1 = ScriptType.ToEnum(typeof(T1)); 192 | ScriptTypes[] args = { t1 }; 193 | Methods.Add(new ScriptCondition(name, condition, args)); 194 | } 195 | 196 | public void AddCondition(string name, Func condition) 197 | { 198 | var t1 = ScriptType.ToEnum(typeof(T1)); 199 | var t2 = ScriptType.ToEnum(typeof(T2)); 200 | ScriptTypes[] args = { t1, t2 }; 201 | Methods.Add(new ScriptCondition(name, condition, args)); 202 | } 203 | 204 | internal List Classes = new List(); 205 | 206 | public ScriptClass AddClass(string name) 207 | { 208 | var newClass = new ScriptClass(name); 209 | Classes.Add(newClass); 210 | return newClass; 211 | } 212 | 213 | public ScriptClass AddClass(string name, Delegate function) 214 | { 215 | var newClass = new ScriptClass(name); 216 | Classes.Add(newClass); 217 | return newClass; 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /Script/Script/ScriptCondition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptCondition : ScriptMethod 10 | { 11 | public ScriptCondition(string name, Delegate condition) 12 | : base(name, condition) 13 | { 14 | Name = name; 15 | Method = condition; 16 | Types = new ScriptTypes[] { }; 17 | ReturnType = ScriptTypes.Boolean; 18 | } 19 | 20 | public ScriptCondition(string name, Delegate condition, ScriptTypes[] types) 21 | : base(name, condition, types, ScriptTypes.Void) 22 | { 23 | Name = name; 24 | Method = condition; 25 | Types = types; 26 | ReturnType = ScriptTypes.Boolean; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Script/Script/ScriptEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | 9 | namespace Script 10 | { 11 | public class ScriptEngine : ScriptClass 12 | { 13 | private string code = ""; 14 | private int indentOffset = 0; 15 | 16 | public ScriptEngine() 17 | { 18 | 19 | } 20 | 21 | public void Execute(string script) 22 | { 23 | code = script; 24 | try 25 | { 26 | Parse(code); 27 | } 28 | catch (ScriptException e) 29 | { 30 | if (Error == null) 31 | { 32 | throw e; 33 | } 34 | else 35 | { 36 | Error.DynamicInvoke(e); 37 | } 38 | } 39 | } 40 | 41 | public T Evaluate(string script) 42 | { 43 | code = script; 44 | try 45 | { 46 | return Parse(code); 47 | } 48 | catch (ScriptException e) 49 | { 50 | if (Error == null) 51 | { 52 | throw e; 53 | } 54 | else 55 | { 56 | Error.DynamicInvoke(e); 57 | } 58 | } 59 | return (T)(object)""; 60 | } 61 | 62 | public void Process(string script) 63 | { 64 | code = script; 65 | } 66 | 67 | public void Trigger(string eventName) 68 | { 69 | Trigger(eventName, new List { }); 70 | } 71 | 72 | public void Trigger(string eventName, object arg1) 73 | { 74 | var args = new List { 75 | new ScriptVariable(arg1) 76 | }; 77 | try 78 | { 79 | Trigger(eventName, args); 80 | } 81 | catch (ScriptException e) 82 | { 83 | if (Error == null) 84 | { 85 | throw e; 86 | } 87 | else 88 | { 89 | Error.DynamicInvoke(e); 90 | } 91 | } 92 | } 93 | 94 | private void Trigger(string eventName, List arguments) 95 | { 96 | TextReader reader = new StringReader(code); 97 | var defs = this.tokenDefinitions.First(x => x.Name == "event"); 98 | defs.TokenDefinitions[0].Matcher = new RegexMatcher(@"event[ ]+" + eventName + @"[ ]*\("); 99 | defs.TokenDefinitions[1].Matcher = new RegexMatcher(@"event[ ]+" + eventName); 100 | Lexer lexer = new Lexer(reader, this.tokenDefinitions, new Action(LexerException)); 101 | lexer.Step("event"); 102 | while (lexer.Next()) 103 | { 104 | if (lexer.Token == Tokens.Block) 105 | { 106 | if (!lexer.Next(true)) 107 | { 108 | break; 109 | } 110 | //this.indentOffset = -1; 111 | Depths[0] = true; 112 | if (lexer.Token == Tokens.EventName) 113 | { 114 | Step(lexer, this); 115 | return; 116 | } 117 | else if (lexer.Token == Tokens.EventNameParameters) 118 | { 119 | var args = StepParameters(lexer); 120 | if (args.Count() != arguments.Count()) 121 | { 122 | throw new ScriptException( 123 | message: String.Format("'{0}' requires {1} properties at Line {2} Col {3}", 124 | eventName, 125 | arguments.Count(), 126 | lexer.LineNumber, 127 | lexer.Position), 128 | row: lexer.LineNumber, 129 | column: lexer.Position 130 | ); 131 | } 132 | for (int i = 0; i < arguments.Count(); i++) 133 | { 134 | SetVariable(args[i], arguments[i]); 135 | } 136 | Step(lexer, this); 137 | return; 138 | } 139 | } 140 | else 141 | { 142 | throw new ScriptException( 143 | message: String.Format("Invalid syntax at Line {0} Col {1}", 144 | lexer.LineNumber, 145 | lexer.Position), 146 | row: lexer.LineNumber, 147 | column: lexer.Position 148 | ); 149 | } 150 | } 151 | //TriggerEvent(lexer, arguments, this); 152 | } 153 | 154 | private int Indent { get; set; } 155 | 156 | // We need to track the boolean values 157 | // be realistic... 20+ depths = terrible script 158 | private Nullable[] Depths = new Nullable[20]; 159 | 160 | private bool DepthCondition() 161 | { 162 | return (bool)Depths[Indent]; 163 | 164 | } 165 | 166 | private Nullable DepthCondition(Nullable result) 167 | { 168 | if (result != null) 169 | { 170 | Depths[Indent] = result; 171 | } 172 | return result; // Makes code look cleaner if it passes through 173 | } 174 | 175 | private bool DepthValidCondition() 176 | { 177 | if ((bool)Depths[Indent]) // if previous block true 178 | { 179 | Depths[Indent] = false; 180 | return false; // set block to false return false 181 | } 182 | else 183 | { 184 | return true; 185 | } 186 | } 187 | 188 | private void DepthInverseCondition() 189 | { 190 | Depths[Indent] = !Depths[Indent]; 191 | } 192 | 193 | public void Exception(Action error) 194 | { 195 | Error = error; 196 | } 197 | 198 | private List tokenDefinitions = new List { 199 | new TokenDefinitionGroup("root", new TokenDefinition[] 200 | { 201 | TokenDefinitions.Comment, 202 | TokenDefinitions.Regex, 203 | TokenDefinitions.String, 204 | TokenDefinitions.Double, 205 | TokenDefinitions.Integer, 206 | TokenDefinitions.Boolean, 207 | TokenDefinitions.Null, 208 | TokenDefinitions.If, 209 | TokenDefinitions.ElseIf, 210 | TokenDefinitions.Else, 211 | TokenDefinitions.For, 212 | TokenDefinitions.Arithmetic, 213 | TokenDefinitions.ListType, 214 | TokenDefinitions.BaseType, 215 | TokenDefinitions.Keyword, 216 | TokenDefinitions.Symbol, 217 | TokenDefinitions.ArrayLeft, 218 | TokenDefinitions.ArrayRight, 219 | TokenDefinitions.Dot, 220 | TokenDefinitions.Comma, 221 | TokenDefinitions.Left, 222 | TokenDefinitions.Right, 223 | TokenDefinitions.Assignment, 224 | TokenDefinitions.Operator, 225 | TokenDefinitions.Tab, 226 | TokenDefinitions.Space 227 | }), 228 | new TokenDefinitionGroup("eventargs", new TokenDefinition[] 229 | { 230 | TokenDefinitions.Symbol, 231 | TokenDefinitions.Comma, 232 | TokenDefinitions.Space, 233 | TokenDefinitions.Right 234 | }), 235 | new TokenDefinitionGroup("parameters", new TokenDefinition[] 236 | { 237 | TokenDefinitions.BaseType, 238 | TokenDefinitions.ListType, 239 | TokenDefinitions.Symbol, 240 | TokenDefinitions.Comma, 241 | TokenDefinitions.Space, 242 | TokenDefinitions.Right 243 | }), 244 | new TokenDefinitionGroup("event", new TokenDefinition[] 245 | { 246 | new TokenDefinition(@"event[ ]+error[ ]*\(", Tokens.EventNameParameters), 247 | new TokenDefinition(@"event[ ]+error", Tokens.EventName) 248 | }) 249 | }; 250 | 251 | private void Parse(string code) 252 | { 253 | Parse(code, 0); 254 | } 255 | 256 | private T Parse(string code) 257 | { 258 | return Parse(code, 0); 259 | } 260 | 261 | private T Parse(string code, int indentOffset) 262 | { 263 | this.indentOffset = indentOffset; 264 | this.Indent = indentOffset; 265 | 266 | TextReader reader = new StringReader(code); 267 | Lexer lexer = new Lexer(reader, this.tokenDefinitions, new Action(LexerException)); 268 | ScriptVariable value = Step(lexer, this); 269 | return value.Return(); 270 | } 271 | 272 | private void LexerException(int lineNumber, int position, string lineRemaining) 273 | { 274 | throw new ScriptException( 275 | message: String.Format("Invalid tokens at Line {0} Col {1}", 276 | lineNumber, 277 | position), 278 | row: lineNumber, 279 | column: position, 280 | method: "undefined" 281 | ); 282 | } 283 | 284 | private ScriptVariable Step(Lexer lexer, ScriptClass classScope) 285 | { 286 | lexer.Step("root"); 287 | ScriptVariable result = new ScriptVariable(); 288 | while (lexer.Next()) 289 | { 290 | switch (lexer.Token) 291 | { 292 | case Tokens.Block: 293 | Indent = indentOffset; 294 | Debug.WriteLine("Block Statement"); 295 | break; 296 | case Tokens.Tab: 297 | Indent++; 298 | Debug.WriteLine("Tab: {0}", Indent); 299 | if (Depths[Indent - 1] == true) 300 | { 301 | continue; 302 | } 303 | else if (Depths[Indent - 1] == false) 304 | { 305 | lexer.SkipBlock(); 306 | continue; 307 | } 308 | else if (Depths[Indent - 1] == null) 309 | { 310 | throw new ScriptException( 311 | message: String.Format("Syntax error on Line {0} Col {1}", 312 | lexer.LineNumber, 313 | lexer.Position), 314 | row: lexer.LineNumber, 315 | column: lexer.Position 316 | ); 317 | } 318 | break; 319 | case Tokens.Symbol: 320 | /*var functionInstances = classScope.Methods.Where(x => x.Name == lexer.TokenContents).ToList(); 321 | if (functionInstances.Count() > 0) 322 | { 323 | Debug.WriteLine("Step Function: {0}", lexer.TokenContents); 324 | if ((Indent - indentOffset) > Depths.Length) 325 | { 326 | var functionInstance = functionInstances.First(); 327 | throw new ScriptException( 328 | message: String.Format("Indented too far \"{0}\" Line {1} Col {2}", 329 | functionInstance.Name, 330 | lexer.LineNumber, 331 | lexer.Position), 332 | row: lexer.LineNumber, 333 | column: lexer.Position, 334 | method: functionInstance.Name 335 | ); 336 | } 337 | else if (Indent == 0 || Depths[Indent - 1 - indentOffset]) 338 | { 339 | result = StepMethod(lexer, functionInstances); // Not capturing just calling 340 | if (classScope.Name != null) 341 | { 342 | break; 343 | } 344 | } 345 | else 346 | { 347 | lexer.SkipBlock(); 348 | break; 349 | } 350 | continue; 351 | } 352 | var classInstance = classScope.Classes.FirstOrDefault(x => x.Name == lexer.TokenContents); 353 | if (classInstance != null) 354 | { 355 | result = Step(lexer, classInstance); 356 | if (classScope.Name == null) 357 | { 358 | continue; 359 | } 360 | else 361 | { 362 | break; 363 | } 364 | }*/ 365 | lexer.Prev(); 366 | return StepValue(lexer); 367 | case Tokens.ListType: 368 | switch (lexer.TokenContents) 369 | { 370 | case "string[]": 371 | StepProperty>(lexer, classScope); 372 | break; 373 | case "int[]": 374 | StepProperty>(lexer, classScope); 375 | break; 376 | case "double[]": 377 | StepProperty>(lexer, classScope); 378 | break; 379 | case "bool[]": 380 | StepProperty>(lexer, classScope); 381 | break; 382 | } 383 | break; 384 | case Tokens.BaseType: 385 | var tempType = lexer.TokenContents; 386 | lexer.Next(); 387 | if (lexer.Token == Tokens.Left) 388 | { 389 | lexer.Prev(); // LEFT 390 | lexer.Prev(); // BASETYPE 391 | return StepValue(lexer, this); 392 | } 393 | else if (lexer.Token == Tokens.Space) 394 | { 395 | switch (tempType) 396 | { 397 | case "string": 398 | StepProperty(lexer, classScope); 399 | break; 400 | case "int": 401 | StepProperty(lexer, classScope); 402 | break; 403 | case "double": 404 | StepProperty(lexer, classScope); 405 | break; 406 | case "bool": 407 | StepProperty(lexer, classScope); 408 | break; 409 | case "var": 410 | StepProperty(lexer, classScope); 411 | break; 412 | } 413 | } 414 | break; 415 | case Tokens.If: 416 | var val = StepValue(lexer); 417 | var check = DepthCondition(val.Return()); 418 | if (check == null) 419 | { 420 | throw new ScriptException("error in if"); 421 | } 422 | Debug.WriteLine("If: {0}", Depths[Indent]); 423 | break; 424 | case Tokens.ElseIf: 425 | if (DepthValidCondition()) // Previous has to be false 426 | { 427 | var check2 = DepthCondition(StepValue(lexer).Return()); 428 | if (check2 == null) 429 | { 430 | Debug.WriteLine("Else If: ERROR"); 431 | throw new ScriptException("error in if"); 432 | } 433 | Debug.WriteLine("Else If: {0}", Depths[Indent]); 434 | } 435 | else // loop through, ignore everything! 436 | { 437 | while (lexer.Next()) 438 | { 439 | if (lexer.Token == Tokens.Block) 440 | { 441 | break; 442 | } 443 | } 444 | // invalid end of script error 445 | } 446 | break; 447 | case Tokens.Else: 448 | DepthInverseCondition(); 449 | Debug.WriteLine("Else: {0}", Depths[Indent]); 450 | break; 451 | case Tokens.For: 452 | break; 453 | case Tokens.String: 454 | lexer.Prev(); 455 | return StepValue(lexer); 456 | case Tokens.Integer: 457 | lexer.Prev(); 458 | return StepValue(lexer); 459 | case Tokens.Double: 460 | lexer.Prev(); 461 | return StepValue(lexer); 462 | case Tokens.Boolean: 463 | lexer.Prev(); 464 | return StepValue(lexer); 465 | case Tokens.Null: 466 | lexer.Prev(); 467 | return StepValue(lexer); 468 | case Tokens.Keyword: 469 | switch (lexer.TokenContents) 470 | { 471 | case "return": 472 | return StepValue(lexer, this); 473 | case "event": 474 | return result; // Stop script 475 | } 476 | break; 477 | default: 478 | throw new ScriptException( 479 | message: String.Format("Unknown keyword {0} on Line {1} Col {2}", 480 | lexer.TokenContents, 481 | lexer.LineNumber, 482 | lexer.Position), 483 | row: lexer.LineNumber, 484 | column: lexer.Position 485 | ); 486 | } 487 | //Debug.WriteLine("Token: {0} Contents: {1}", lexer.Token, lexer.TokenContents); 488 | } 489 | return result; 490 | throw new ScriptException( 491 | message: String.Format("Invalid lexer step on Line {1} Col {2}", 492 | lexer.LineNumber, 493 | lexer.Position), 494 | row: lexer.LineNumber, 495 | column: lexer.Position 496 | ); 497 | } 498 | 499 | private void StepProperty(Lexer lexer, ScriptClass classScope) 500 | { 501 | var name = ""; 502 | while (lexer.Next()) 503 | { 504 | if (lexer.Token == Tokens.Space) { } 505 | else if (lexer.Token == Tokens.Symbol) 506 | { 507 | name = lexer.TokenContents; 508 | } 509 | else if (name != "" && lexer.Token == Tokens.Assignment) 510 | { 511 | ScriptTypes type = ScriptType.ToEnum(typeof(T)); 512 | var variable = StepValue(lexer); 513 | if (variable.Type == ScriptTypes.Undefined && ScriptType.IsList(type)) 514 | { 515 | variable.Type = type; 516 | } 517 | if (type == ScriptTypes.Any || type == variable.Type) 518 | { 519 | SetVariable(name, variable); 520 | } 521 | else 522 | { 523 | lexer.Prev(); 524 | lexer.Prev(); 525 | throw new ScriptException( 526 | message: String.Format("{0} '{1}' set to {2} on Line {3} Col {4}", 527 | type.ToString(), 528 | name, 529 | variable.Type.ToString(), 530 | lexer.LineNumber, 531 | lexer.Position), 532 | row: lexer.LineNumber, 533 | column: lexer.Position 534 | ); 535 | } 536 | return; 537 | } 538 | else 539 | { 540 | break; 541 | } 542 | } 543 | } 544 | 545 | private ReturnT StepValue(Lexer lexer) 546 | { 547 | var value = StepValue(lexer, this); 548 | return value.Cast(lexer).Return(); 549 | } 550 | 551 | private ScriptVariable StepValue(Lexer lexer) 552 | { 553 | return StepValue(lexer, this); 554 | } 555 | 556 | private ReturnT StepValue(Lexer lexer, ScriptClass classScope) 557 | { 558 | var value = StepValue(lexer, classScope); 559 | return value.Cast(lexer).Return(); 560 | } 561 | 562 | /// 563 | /// Step for complex value 564 | /// 565 | /// Lexer 566 | /// Valid value or null 567 | private ScriptVariable StepValue(Lexer lexer, ScriptClass classScope) 568 | { 569 | var current = new ScriptVariable(); 570 | while (lexer.Next()) 571 | { 572 | switch (lexer.Token) 573 | { 574 | case Tokens.Space: 575 | break; 576 | case Tokens.Block: 577 | return current; 578 | case Tokens.Null: 579 | current.Type = ScriptTypes.Null; 580 | current.Value = null; 581 | break; 582 | case Tokens.BaseType: 583 | var castType = lexer.TokenContents; 584 | lexer.Next(); 585 | if (lexer.Token == Tokens.Left) 586 | { 587 | var fromValue = StepValue(lexer); 588 | switch (castType) 589 | { 590 | case "string": 591 | return fromValue.Cast(lexer); 592 | case "int": 593 | return fromValue.Cast(lexer); 594 | case "double": 595 | return fromValue.Cast(lexer); 596 | case "bool": 597 | return fromValue.Cast(lexer); 598 | } 599 | 600 | } 601 | // Error should be impossible 602 | break; 603 | case Tokens.Comma: 604 | lexer.Prev(); 605 | return current; 606 | case Tokens.ArrayRight: 607 | lexer.Prev(); 608 | return current; 609 | case Tokens.Dot: 610 | lexer.Next(); 611 | if (lexer.Token == Tokens.Symbol && current.Type == ScriptTypes.Undefined) 612 | { 613 | // Classes 614 | var classInstance2 = classScope.Classes.FirstOrDefault(x => x.Name == lexer.TokenContents); 615 | if (classInstance2 != null) 616 | { 617 | var result = StepValue(lexer, classInstance2); 618 | continue; 619 | } 620 | // Methods 621 | var methodInstances = classScope.Methods.Where(x => x.Name == lexer.TokenContents).ToList(); 622 | if (methodInstances.Count() > 0) 623 | { 624 | return StepMethod(lexer, methodInstances); 625 | } 626 | // Properties 627 | var propertyInstances = classScope.Properties.FirstOrDefault(x => x.Name == lexer.TokenContents); 628 | if (propertyInstances != null) 629 | { 630 | return propertyInstances; 631 | } 632 | } 633 | else if (lexer.Token == Tokens.Symbol) 634 | { 635 | // Typed Functions 636 | var typeFunctionInstances = TypeFunctions.Where(x => x.ExtendType == current.Type && x.Name == lexer.TokenContents).Select(x => (ScriptTypeMethod)x).ToList(); 637 | if (typeFunctionInstances.Count() > 0) 638 | { 639 | current = StepTypeFunction(lexer, typeFunctionInstances, current); 640 | continue; 641 | } 642 | throw new ScriptException( 643 | message: String.Format("Type '{0}' has no method named '{1}' on Line {2} Col {3}", 644 | current.Type.ToString(), 645 | lexer.TokenContents, 646 | lexer.LineNumber, 647 | lexer.Position), 648 | row: lexer.LineNumber, 649 | column: lexer.Position, 650 | method: lexer.TokenContents 651 | ); 652 | } 653 | lexer.Prev(); 654 | throw new ScriptException( 655 | message: String.Format("Syntax error on Line {0} Col {1}", 656 | lexer.LineNumber, 657 | lexer.Position), 658 | row: lexer.LineNumber, 659 | column: lexer.Position 660 | ); 661 | case Tokens.Symbol: 662 | // Classes 663 | var classInstance = Classes.FirstOrDefault(x => x.Name == lexer.TokenContents); 664 | if (classInstance != null) 665 | { 666 | return StepValue(lexer, classInstance); 667 | } 668 | // Variables 669 | var variable = Variables.FirstOrDefault(p => p.Name == lexer.TokenContents); 670 | if (variable != null) 671 | { 672 | //if (ScriptType.IsList(variable.Type)) 673 | //{ 674 | // var index = StepValue(lexer); 675 | // var list = ((List)(variable.Value)); 676 | // if (index >= list.Count()) 677 | // { 678 | // throw new ScriptException( 679 | // message: String.Format("Property '{0}' contains {1} items (not {2}) on Line {3} Col {4}", 680 | // variable.Name, 681 | // list.Count(), 682 | // index + 1, 683 | // lexer.LineNumber, 684 | // lexer.Position), 685 | // row: lexer.LineNumber, 686 | // column: lexer.Position, 687 | // method: lexer.TokenContents 688 | // ); 689 | // } 690 | // return list[index]; 691 | //} 692 | //else 693 | //{ 694 | current.Type = variable.Type; 695 | current.Value = variable.Value; 696 | continue; 697 | //} 698 | } 699 | // Functions 700 | var functionInstances = Methods.Where(x => x.Name == lexer.TokenContents).ToList(); 701 | if (functionInstances.Count() > 0) 702 | { 703 | current = StepMethod(lexer, functionInstances); 704 | break; 705 | } 706 | lexer.Prev(); 707 | throw new ScriptException( 708 | message: String.Format("Undefined '{0}' on Line {1} Col {2}", 709 | lexer.TokenContents, 710 | lexer.LineNumber, 711 | lexer.Position), 712 | row: lexer.LineNumber, 713 | column: lexer.Position, 714 | method: lexer.TokenContents 715 | ); 716 | case Tokens.Right: 717 | // No pemdas support, fix this later on! 718 | return current; 719 | case Tokens.ArrayLeft: 720 | if (current.Type == ScriptTypes.Undefined) 721 | { 722 | current = StepList(lexer); 723 | } 724 | else 725 | { 726 | if (ScriptType.IsList(current.Type)) 727 | { 728 | var index = StepValue(lexer); 729 | var list = ((List)(current.Value)); 730 | if (index >= list.Count()) 731 | { 732 | throw new ScriptException( 733 | message: String.Format("Property '{0}' contains {1} items (not {2}) on Line {3} Col {4}", 734 | current.Name, 735 | list.Count(), 736 | index + 1, 737 | lexer.LineNumber, 738 | lexer.Position), 739 | row: lexer.LineNumber, 740 | column: lexer.Position, 741 | method: lexer.TokenContents 742 | ); 743 | } 744 | return list[index]; 745 | } 746 | else 747 | { 748 | 749 | } 750 | } 751 | break; 752 | case Tokens.String: 753 | if (current.Type != ScriptTypes.Undefined) 754 | { 755 | lexer.Prev(); 756 | throw new ScriptException( 757 | message: String.Format("Unexpected string on Line {0} Col {1}", 758 | lexer.LineNumber, 759 | lexer.Position), 760 | row: lexer.LineNumber, 761 | column: lexer.Position 762 | ); 763 | } 764 | current.Type = ScriptTypes.String; 765 | current.Value = lexer.TokenContents.Substring(1, lexer.TokenContents.Length - 2); 766 | break; 767 | case Tokens.Integer: 768 | current.Type = ScriptTypes.Integer; 769 | current.Value = int.Parse(lexer.TokenContents); 770 | break; 771 | case Tokens.Double: 772 | current.Type = ScriptTypes.Double; 773 | current.Value = double.Parse(lexer.TokenContents); 774 | break; 775 | case Tokens.Boolean: 776 | current.Type = ScriptTypes.Boolean; 777 | current.Value = lexer.TokenContents == "true"; 778 | break; 779 | case Tokens.Regex: 780 | if (current.Type != ScriptTypes.Undefined) { return current; } 781 | current.Type = ScriptTypes.Regex; 782 | var optionsChars = lexer.TokenContents.Substring(lexer.TokenContents.LastIndexOf('/') + 1).ToCharArray(); 783 | var options = RegexOptions.ECMAScript; 784 | if (optionsChars.Contains('i')) 785 | { 786 | options |= RegexOptions.IgnoreCase; 787 | } 788 | if (optionsChars.Contains('m')) 789 | { 790 | options |= RegexOptions.Multiline; 791 | } 792 | if (optionsChars.Contains('s')) 793 | { 794 | options |= RegexOptions.Singleline; 795 | } 796 | current.Value = new Regex(lexer.TokenContents.Substring(1, lexer.TokenContents.LastIndexOf('/') - 1), options); 797 | break; 798 | case Tokens.Operator: 799 | if (lexer.TokenContents == "and") 800 | { 801 | current.Value = current.Cast(lexer).Return() && StepValue(lexer); 802 | } 803 | else if (lexer.TokenContents == "or") 804 | { 805 | current.Value = current.Cast(lexer).Return() || StepValue(lexer); 806 | } 807 | break; 808 | case Tokens.Arithmetic: 809 | var symbol = lexer.TokenContents; 810 | var next = StepValue(lexer); 811 | switch (symbol) 812 | { 813 | case "+": 814 | if (current.Type == ScriptTypes.Integer && next.Type == ScriptTypes.Integer) 815 | { 816 | current.Value = (int)current.Value + (int)next.Value; 817 | current.Type = ScriptTypes.Integer; 818 | } 819 | else if (current.Type == ScriptTypes.Integer && next.Type == ScriptTypes.ListString) 820 | { 821 | current.Value = current.Value.ToString() + string.Join(",", next.Return>()); 822 | current.Type = ScriptTypes.String; 823 | } 824 | else if (current.Type == ScriptTypes.Integer && next.Type == ScriptTypes.Double) 825 | { 826 | current.Value = current.Cast(lexer).Return() + next.Cast(lexer).Return(); 827 | current.Type = ScriptTypes.Double; 828 | } 829 | else 830 | { 831 | current.Value = current.Value.ToString() + next.Value.ToString(); 832 | current.Type = ScriptTypes.String; 833 | } 834 | break; 835 | case "-": 836 | if (current.Type == ScriptTypes.Integer && next.Type == ScriptTypes.Integer) 837 | { 838 | current.Value = (int)current.Value - (int)next.Value; 839 | current.Type = ScriptTypes.Integer; 840 | } 841 | else 842 | { 843 | current.Value = current.Cast(lexer).Return() - next.Cast(lexer).Return(); 844 | current.Type = ScriptTypes.Double; 845 | } 846 | break; 847 | case "*": 848 | if (current.Type == ScriptTypes.Integer && next.Type == ScriptTypes.Integer) 849 | { 850 | current.Value = (int)current.Value * (int)next.Value; 851 | current.Type = ScriptTypes.Integer; 852 | } 853 | else 854 | { 855 | current.Value = current.Cast(lexer).Return() * next.Cast(lexer).Return(); 856 | current.Type = ScriptTypes.Double; 857 | } 858 | break; 859 | case "/": 860 | if (current.Type == ScriptTypes.Integer) 861 | { 862 | if (current.Type == ScriptTypes.Integer && next.Type == ScriptTypes.Integer) 863 | { 864 | current.Value = current.Cast(lexer).Return() / next.Cast(lexer).Return(); 865 | current.Type = ScriptTypes.Double; 866 | } 867 | else 868 | { 869 | current.Value = current.Cast(lexer).Return() / next.Cast(lexer).Return(); 870 | current.Type = ScriptTypes.Double; 871 | } 872 | } 873 | break; 874 | } 875 | break; 876 | default: 877 | return current; 878 | } 879 | } 880 | // Syntax error thrown here 881 | return current; 882 | } 883 | 884 | private ScriptVariable StepList(Lexer lexer) 885 | { 886 | var type = ScriptTypes.Undefined; 887 | var items = new List(); 888 | var hasComma = true; 889 | while (lexer.Next()) 890 | { 891 | if (lexer.Token == Tokens.Space) { } 892 | else if (lexer.Token == Tokens.ArrayRight) 893 | { 894 | type = type == ScriptTypes.String ? ScriptTypes.ListString 895 | : type == ScriptTypes.Integer ? ScriptTypes.ListInteger 896 | : type == ScriptTypes.Double ? ScriptTypes.ListDouble 897 | : type == ScriptTypes.Boolean ? ScriptTypes.ListBoolean 898 | : ScriptTypes.Undefined; 899 | return new ScriptVariable(items, type); 900 | } 901 | else if (lexer.Token == Tokens.Comma) 902 | { 903 | hasComma = true; 904 | } 905 | else if (hasComma) 906 | { 907 | lexer.Prev(); 908 | var variable = StepValue(lexer); 909 | if (type == ScriptTypes.Undefined) 910 | { 911 | type = variable.Type; 912 | } 913 | else if (type != variable.Type) 914 | { 915 | lexer.Prev(); 916 | throw new ScriptException( 917 | message: String.Format("Invalid data type '{0}' in '{1}' list near Line {2} Col {3}", 918 | type.ToString(), 919 | variable.Type.ToString(), 920 | lexer.LineNumber, 921 | lexer.Position), 922 | row: lexer.LineNumber, 923 | column: lexer.Position 924 | ); 925 | } 926 | items.Add(variable); 927 | hasComma = false; 928 | } 929 | else 930 | { 931 | throw new ScriptException( 932 | message: String.Format("Missing \",\" near Line {0} Col {1}", 933 | lexer.LineNumber, 934 | lexer.Position), 935 | row: lexer.LineNumber, 936 | column: lexer.Position 937 | ); 938 | } 939 | } 940 | throw new ScriptException( 941 | message: String.Format("Missing \"]\" near Line {0} Col {1}", 942 | lexer.LineNumber, 943 | lexer.Position), 944 | row: lexer.LineNumber, 945 | column: lexer.Position 946 | ); 947 | } 948 | 949 | /// 950 | /// Simply call the StepFunction 951 | /// 952 | /// 953 | /// 954 | /// 955 | private ScriptVariable StepTypeFunction(Lexer lexer, List functionTypeInstances, ScriptVariable parentValue) 956 | { 957 | return StepTypeMethod(lexer, functionTypeInstances, parentValue); 958 | } 959 | 960 | private ScriptVariable StepMethod(Lexer lexer, List functionInstances) 961 | { 962 | return StepMethod(lexer, functionInstances, new ScriptVariable()); 963 | } 964 | 965 | private List StepParameters(Lexer lexer) 966 | { 967 | lexer.Step("eventargs"); 968 | var args = new List(); 969 | var usedComma = true; 970 | while (lexer.Next()) 971 | { 972 | if (lexer.Token == Tokens.Space) { } 973 | else if (lexer.Token == Tokens.Comma) 974 | { 975 | usedComma = true; 976 | } 977 | else if (lexer.Token == Tokens.Right) 978 | { 979 | goto DoneArgs; 980 | } 981 | else if (lexer.Token == Tokens.Symbol) 982 | { 983 | if (usedComma) 984 | { 985 | args.Add(lexer.TokenContents); 986 | usedComma = false; 987 | } 988 | else 989 | { 990 | throw new ScriptException( 991 | message: String.Format("Missing comma in argument list on Line {0} Col {1}", 992 | lexer.LineNumber, 993 | lexer.Position), 994 | row: lexer.LineNumber, 995 | column: lexer.Position 996 | ); 997 | } 998 | } 999 | } 1000 | DoneArgs: 1001 | return args; 1002 | } 1003 | 1004 | private List StepArguments(Lexer lexer) 1005 | { 1006 | var args = new List(); 1007 | string MethodName = lexer.TokenContents; 1008 | 1009 | while (lexer.Next()) 1010 | { 1011 | if (lexer.Token == Tokens.Left) 1012 | { 1013 | var usedComma = true; 1014 | while (lexer.Next()) 1015 | { 1016 | if (lexer.Token == Tokens.Space) { } 1017 | else if (lexer.Token == Tokens.Comma) 1018 | { 1019 | usedComma = true; 1020 | } 1021 | else if (lexer.Token == Tokens.Right) 1022 | { 1023 | goto DoneArgs; 1024 | } 1025 | else 1026 | { 1027 | if (usedComma) 1028 | { 1029 | lexer.Prev(); 1030 | args.Add(StepValue(lexer)); 1031 | usedComma = false; 1032 | if (lexer.Token == Tokens.Right) 1033 | { 1034 | goto DoneArgs; 1035 | } 1036 | else 1037 | { 1038 | //lexer.Prev(); 1039 | } 1040 | } 1041 | else 1042 | { 1043 | throw new ScriptException( 1044 | message: String.Format("Missing comma in function call \"{0}\" Line {1} Col {2}", 1045 | MethodName, 1046 | lexer.LineNumber, 1047 | lexer.Position), 1048 | row: lexer.LineNumber, 1049 | column: lexer.Position, 1050 | method: MethodName 1051 | ); 1052 | } 1053 | } 1054 | } 1055 | } 1056 | } 1057 | DoneArgs: 1058 | return args; 1059 | } 1060 | 1061 | private ScriptVariable StepMethod(Lexer lexer, List functionInstances, ScriptVariable parentValue) 1062 | { 1063 | var args = StepArguments(lexer); 1064 | if (args == null) 1065 | { 1066 | throw new ScriptException( 1067 | message: String.Format("Syntax error in arguments for \"{0}\" Line {1} Col {2}", 1068 | "test", 1069 | lexer.LineNumber, 1070 | lexer.Position), 1071 | row: lexer.LineNumber, 1072 | column: lexer.Position, 1073 | method: "test" 1074 | ); 1075 | } 1076 | foreach (var functionInstance in functionInstances) 1077 | { 1078 | if (args.Select(pair => pair.Type).SequenceEqual(functionInstance.Types)) 1079 | { 1080 | if (parentValue.Type != ScriptTypes.Undefined) 1081 | { 1082 | args.Insert(0, parentValue); 1083 | } 1084 | return new ScriptVariable(functionInstance.Method.DynamicInvoke(args.Select(pair => 1085 | { 1086 | switch (pair.Type) 1087 | { 1088 | case ScriptTypes.Regex: 1089 | return pair.Return(); 1090 | case ScriptTypes.ListString: 1091 | return pair.Return>(); 1092 | default: 1093 | return pair.Value; 1094 | } 1095 | }).ToArray()), functionInstance.ReturnType); 1096 | } 1097 | } 1098 | throw new ScriptException( 1099 | message: String.Format("Invalid arguments in \"{0}\" Line {1} Col {2}", 1100 | "test", 1101 | lexer.LineNumber, 1102 | lexer.Position), 1103 | row: lexer.LineNumber, 1104 | column: lexer.Position, 1105 | method: "test" 1106 | ); 1107 | } 1108 | 1109 | private ScriptVariable StepTypeMethod(Lexer lexer, List functionInstances, ScriptVariable parentValue) 1110 | { 1111 | var args = StepArguments(lexer); 1112 | foreach (var functionInstance in functionInstances) 1113 | { 1114 | if (args.Select(pair => pair.Type).SequenceEqual(functionInstance.Types)) 1115 | { 1116 | if (parentValue.Type != ScriptTypes.Undefined) 1117 | { 1118 | args.Insert(0, parentValue); 1119 | } 1120 | var returnVariable = functionInstance.Method.DynamicInvoke(args.Select(pair => 1121 | { 1122 | switch (pair.Type) 1123 | { 1124 | case ScriptTypes.Regex: 1125 | return pair.Return(); 1126 | case ScriptTypes.ListString: 1127 | return pair.Return>(); 1128 | default: 1129 | return pair.Value; 1130 | } 1131 | }).ToArray()); 1132 | switch (functionInstance.ReturnType) 1133 | { 1134 | case ScriptTypes.ListString: 1135 | case ScriptTypes.ListInteger: 1136 | case ScriptTypes.ListDouble: 1137 | case ScriptTypes.ListBoolean: 1138 | return new ScriptVariable(((List)returnVariable).Select(x => new ScriptVariable((object)x, ScriptTypes.String)).ToList(), functionInstance.ReturnType); 1139 | default: 1140 | return new ScriptVariable(returnVariable, functionInstance.ReturnType); 1141 | } 1142 | } 1143 | } 1144 | throw new ScriptException( 1145 | message: String.Format("Invalid arguments in \"{0}\" Line {1} Col {2}", 1146 | "test", 1147 | lexer.LineNumber, 1148 | lexer.Position), 1149 | row: lexer.LineNumber, 1150 | column: lexer.Position 1151 | ); 1152 | } 1153 | 1154 | private void StepArray(Lexer lexer, out ScriptTypes type, out object list) 1155 | { 1156 | List array = new List(); 1157 | while (lexer.Next()) 1158 | { 1159 | if (lexer.Token == Tokens.String) 1160 | { 1161 | type = ScriptTypes.ListString; 1162 | array.Add(lexer.TokenContents.Substring(1, lexer.TokenContents.Length - 2)); 1163 | } 1164 | else if (lexer.Token == Tokens.Double) 1165 | { 1166 | type = ScriptTypes.ListDouble; 1167 | array.Add(double.Parse(lexer.TokenContents)); 1168 | } 1169 | else if (lexer.Token == Tokens.Integer) 1170 | { 1171 | type = ScriptTypes.ListInteger; 1172 | array.Add(int.Parse(lexer.TokenContents)); 1173 | } 1174 | else if (lexer.Token == Tokens.Boolean) 1175 | { 1176 | type = ScriptTypes.ListBoolean; 1177 | array.Add(lexer.TokenContents == "true"); 1178 | } 1179 | else if (lexer.Token == Tokens.ArrayRight) 1180 | { 1181 | list = array.ToList(); 1182 | } 1183 | } 1184 | throw new ScriptException( 1185 | message: String.Format("Invalid list syntax Line {0} Col {1}", 1186 | lexer.LineNumber, 1187 | lexer.Position), 1188 | row: lexer.LineNumber, 1189 | column: lexer.Position, 1190 | method: "array" 1191 | ); 1192 | } 1193 | 1194 | private void TriggerEvent(Lexer lexer, List arguments, ScriptClass classInstance) 1195 | { 1196 | while (lexer.Next()) 1197 | { 1198 | if (lexer.Token == Tokens.EventName) 1199 | { 1200 | lexer.Next(); 1201 | if (lexer.Token == Tokens.Arguments) 1202 | { 1203 | var args = lexer.TokenContents.Substring(1, lexer.TokenContents.Length - 2).Replace(" ", ""); 1204 | 1205 | Debug.WriteLine("Args: {0}", lexer.TokenContents); 1206 | lexer.Next(); 1207 | } 1208 | if (lexer.Token == Tokens.Block) 1209 | { 1210 | var script = new StringBuilder(); 1211 | while (lexer.Next()) 1212 | { 1213 | if (lexer.Token == Tokens.Block) { continue; } 1214 | if (lexer.Token == Tokens.Code) 1215 | { 1216 | script.AppendLine(lexer.TokenContents); 1217 | } 1218 | else 1219 | { 1220 | break; 1221 | } 1222 | } 1223 | Debug.WriteLine("Run: {0}", script.ToString()); 1224 | Depths[0] = true; 1225 | Parse(script.ToString(), 1); 1226 | } 1227 | else 1228 | { 1229 | throw new ScriptException( 1230 | message: String.Format("Invalid syntax Line {0} Col {1}", 1231 | lexer.LineNumber, 1232 | lexer.Position), 1233 | row: lexer.LineNumber, 1234 | column: lexer.Position 1235 | ); 1236 | } 1237 | } 1238 | Debug.WriteLine("Token: {0} Contents: {1}", lexer.Token, lexer.TokenContents); 1239 | } 1240 | } 1241 | 1242 | private List TypeFunctions = new List(); 1243 | 1244 | public void TypeFunction(string methodName, Func method) 1245 | { 1246 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1247 | var returnT = ScriptType.ToEnum(typeof(ReturnT)); 1248 | TypeFunctions.Add(new ScriptTypeFunction(inputT, methodName, method, returnT)); 1249 | } 1250 | 1251 | public void TypeFunction(string methodName, Func method) 1252 | { 1253 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1254 | var t1 = ScriptType.ToEnum(typeof(T1)); 1255 | var returnT = ScriptType.ToEnum(typeof(ReturnT)); 1256 | ScriptTypes[] args = { t1 }; 1257 | TypeFunctions.Add(new ScriptTypeFunction(inputT, methodName, method, args, returnT)); 1258 | } 1259 | 1260 | public void TypeFunction(string methodName, Func method) 1261 | { 1262 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1263 | var t1 = ScriptType.ToEnum(typeof(T1)); 1264 | var t2 = ScriptType.ToEnum(typeof(T2)); 1265 | var returnT = ScriptType.ToEnum(typeof(ReturnT)); 1266 | ScriptTypes[] args = { t1, t2 }; 1267 | TypeFunctions.Add(new ScriptTypeFunction(inputT, methodName, method, args, returnT)); 1268 | } 1269 | 1270 | private List TypeConditions = new List(); 1271 | public void TypeCondition(string methodName, Func method) 1272 | { 1273 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1274 | TypeConditions.Add(new ScriptTypeCondition(inputT, methodName, method)); 1275 | } 1276 | 1277 | public void TypeCondition(string methodName, Func method) 1278 | { 1279 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1280 | var t1 = ScriptType.ToEnum(typeof(T1)); 1281 | ScriptTypes[] args = { t1 }; 1282 | TypeConditions.Add(new ScriptTypeCondition(inputT, methodName, method, args)); 1283 | } 1284 | public void TypeCondition(string methodName, Func method) 1285 | { 1286 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1287 | var t1 = ScriptType.ToEnum(typeof(T1)); 1288 | var t2 = ScriptType.ToEnum(typeof(T2)); 1289 | ScriptTypes[] args = { t1, t2 }; 1290 | TypeConditions.Add(new ScriptTypeCondition(inputT, methodName, method, args)); 1291 | } 1292 | 1293 | private List TypeProperties = new List(); 1294 | 1295 | public void TypeProperty(string propertyName, Func method) 1296 | { 1297 | var inputT = ScriptType.ToEnum(typeof(InputT)); 1298 | TypeProperties.Add(new ScriptTypeProperty(inputT, propertyName, method)); 1299 | } 1300 | } 1301 | } 1302 | -------------------------------------------------------------------------------- /Script/Script/ScriptException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptException : Exception 10 | { 11 | public ScriptException(string message, int column = 0, int row = 0, string method = null) : base(message) 12 | { 13 | Row = row; 14 | Column = column; 15 | Method = method; 16 | } 17 | 18 | public string Method { get; set; } 19 | 20 | public int Column { get; set; } 21 | 22 | public int Row { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Script/Script/ScriptFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptFunction : ScriptMethod 10 | { 11 | 12 | public ScriptFunction(string name, Delegate function) : base(name, function) 13 | { 14 | Name = name; 15 | Method = function; 16 | Types = new ScriptTypes[] { }; 17 | ReturnType = ScriptTypes.Void; 18 | } 19 | 20 | public ScriptFunction(string name, Delegate function, ScriptTypes returnType) : base(name, function, returnType) 21 | { 22 | Name = name; 23 | Method = function; 24 | Types = new ScriptTypes[] { }; 25 | ReturnType = returnType; 26 | } 27 | 28 | public ScriptFunction(string name, Delegate function, ScriptTypes[] types) : base(name, function, types) 29 | { 30 | Name = name; 31 | Method = function; 32 | Types = types; 33 | ReturnType = ScriptTypes.Void; 34 | } 35 | 36 | public ScriptFunction(string name, Delegate function, ScriptTypes[] types, ScriptTypes returnType) : base(name, function, types, returnType) 37 | { 38 | Name = name; 39 | Method = function; 40 | Types = types; 41 | ReturnType = returnType; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Script/Script/ScriptMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptMethod 10 | { 11 | public string Name { get; set; } 12 | public Delegate Method { get; set; } 13 | public ScriptTypes[] Types { get; set; } 14 | public ScriptTypes ReturnType { get; set; } 15 | 16 | public ScriptMethod(string name, Delegate method) 17 | { 18 | Name = name; 19 | Method = method; 20 | Types = new ScriptTypes[] { }; 21 | ReturnType = ScriptTypes.Void; 22 | } 23 | 24 | public ScriptMethod(string name, Delegate method, ScriptTypes returnType) 25 | { 26 | Name = name; 27 | Method = method; 28 | Types = new ScriptTypes[] { }; 29 | ReturnType = returnType; 30 | } 31 | 32 | public ScriptMethod(string name, Delegate method, ScriptTypes[] types) 33 | { 34 | Name = name; 35 | Method = method; 36 | Types = types; 37 | ReturnType = ScriptTypes.Void; 38 | } 39 | 40 | public ScriptMethod(string name, Delegate method, ScriptTypes[] types, ScriptTypes returnType) 41 | { 42 | Name = name; 43 | Method = method; 44 | Types = types; 45 | ReturnType = returnType; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Script/Script/ScriptProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | internal class ScriptProperty 10 | { 11 | public String Name { get; set; } 12 | 13 | public object Value { get; set; } 14 | 15 | public ScriptTypes Type { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Script/Script/ScriptScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Script 7 | { 8 | public class ScriptScope 9 | { 10 | public ScriptScope(ScriptException error) 11 | { 12 | Indent = 0; 13 | Error = error; 14 | } 15 | 16 | private ScriptException Error { get; set; } 17 | 18 | public int Indent { get; set; } 19 | 20 | // We need to track the boolean values 21 | public List Depths = new List(); 22 | 23 | public void DepthCondition(bool result) 24 | { 25 | if (Depths.Count() < Indent) 26 | { 27 | Depths.Add(result); 28 | } 29 | else 30 | { 31 | Depths[Indent] = result; 32 | } 33 | } 34 | 35 | public void DepthInverseCondition() 36 | { 37 | if (Depths.Count() < Indent) 38 | { 39 | Depths[Indent] = !Depths[Indent - 1]; 40 | } 41 | else 42 | { 43 | 44 | } 45 | 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Script/Script/ScriptType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | 8 | namespace Script 9 | { 10 | public static class ScriptType 11 | { 12 | public static ScriptTypes ToEnum(Type o) 13 | { 14 | return o == typeof(string) ? ScriptTypes.String 15 | : o == typeof(int) ? ScriptTypes.Integer 16 | : o == typeof(double) ? ScriptTypes.Double 17 | : o == typeof(bool) ? ScriptTypes.Boolean 18 | : o == typeof(Regex) ? ScriptTypes.Regex 19 | : o == typeof(List) ? ScriptTypes.ListString 20 | : o == typeof(List) ? ScriptTypes.ListInteger 21 | : o == typeof(List) ? ScriptTypes.ListDouble 22 | : o == typeof(List) ? ScriptTypes.ListBoolean 23 | : ScriptTypes.Any; 24 | } 25 | 26 | public static bool IsList(ScriptTypes type) 27 | { 28 | switch(type) 29 | { 30 | case ScriptTypes.ListString: 31 | case ScriptTypes.ListInteger: 32 | case ScriptTypes.ListDouble: 33 | case ScriptTypes.ListBoolean: 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Script/Script/ScriptTypeCondition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptTypeCondition : ScriptTypeMethod 10 | { 11 | 12 | public ScriptTypeCondition(ScriptTypes extendType, string name, Delegate condition) : base (extendType, name, condition) 13 | { 14 | ExtendType = extendType; 15 | Name = name; 16 | Method = condition; 17 | Types = new ScriptTypes[] { }; 18 | ReturnType = ScriptTypes.Boolean; 19 | } 20 | 21 | public ScriptTypeCondition(ScriptTypes extendType, string name, Delegate condition, ScriptTypes[] types) : base(extendType, name, condition, types) 22 | { 23 | ExtendType = extendType; 24 | Name = name; 25 | Method = condition; 26 | Types = types; 27 | ReturnType = ScriptTypes.Boolean; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Script/Script/ScriptTypeFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptTypeFunction : ScriptTypeMethod 10 | { 11 | 12 | public ScriptTypeFunction(ScriptTypes extendType, string name, Delegate function, ScriptTypes returnType) : base(extendType, name, function, returnType) 13 | { 14 | ExtendType = extendType; 15 | Name = name; 16 | Method = function; 17 | Types = new ScriptTypes[] { }; 18 | ReturnType = returnType; 19 | } 20 | 21 | public ScriptTypeFunction(ScriptTypes extendType, string name, Delegate function, ScriptTypes[] types, ScriptTypes returnType) : base(extendType, name, function, types, returnType) 22 | { 23 | ExtendType = extendType; 24 | Name = name; 25 | Method = function; 26 | Types = types; 27 | ReturnType = returnType; 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Script/Script/ScriptTypeMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptTypeMethod 10 | { 11 | public ScriptTypes ExtendType { get; set; } 12 | public string Name { get; set; } 13 | public Delegate Method { get; set; } 14 | public ScriptTypes[] Types { get; set; } 15 | public ScriptTypes ReturnType { get; set; } 16 | 17 | public ScriptTypeMethod(ScriptTypes extendType, string name, Delegate method) 18 | { 19 | ExtendType = extendType; 20 | Name = name; 21 | Method = method; 22 | Types = new ScriptTypes[] { }; 23 | ReturnType = ScriptTypes.Void; 24 | } 25 | 26 | public ScriptTypeMethod(ScriptTypes extendType, string name, Delegate method, ScriptTypes returnType) 27 | { 28 | ExtendType = extendType; 29 | Name = name; 30 | Method = method; 31 | Types = new ScriptTypes[] { }; 32 | ReturnType = returnType; 33 | } 34 | 35 | public ScriptTypeMethod(ScriptTypes extendType, string name, Delegate method, ScriptTypes[] types) 36 | { 37 | ExtendType = extendType; 38 | Name = name; 39 | Method = method; 40 | Types = types; 41 | ReturnType = ScriptTypes.Void; 42 | } 43 | 44 | public ScriptTypeMethod(ScriptTypes extendType, string name, Delegate method, ScriptTypes[] types, ScriptTypes returnType) 45 | { 46 | ExtendType = extendType; 47 | Name = name; 48 | Method = method; 49 | Types = types; 50 | ReturnType = returnType; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Script/Script/ScriptTypeProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public class ScriptTypeProperty 10 | { 11 | public ScriptTypes ExtendType { get; set; } 12 | public string Name { get; set; } 13 | public Delegate Function { get; set; } 14 | 15 | public ScriptTypeProperty(ScriptTypes extendType, string name, Delegate function) 16 | { 17 | ExtendType = extendType; 18 | Name = name; 19 | Function = function; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Script/Script/ScriptTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public enum ScriptTypes 10 | { 11 | Any, 12 | Integer, 13 | Double, 14 | String, 15 | Boolean, 16 | ListInteger, 17 | ListDouble, 18 | ListString, 19 | ListBoolean, 20 | Regex, 21 | Null, 22 | Undefined, 23 | Void 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Script/Script/ScriptVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | 8 | namespace Script 9 | { 10 | public class ScriptVariable 11 | { 12 | 13 | public object Value { get; set; } 14 | 15 | public ScriptTypes Type { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | public ScriptVariable() 20 | { 21 | Value = null; 22 | Type = ScriptTypes.Undefined; 23 | } 24 | 25 | public ScriptVariable(object value) 26 | { 27 | Value = value; 28 | Type = value is string ? ScriptTypes.String 29 | : value is int ? ScriptTypes.Integer 30 | : value is double ? ScriptTypes.Double 31 | : value is bool ? ScriptTypes.Boolean 32 | : value is Regex ? ScriptTypes.Regex 33 | : value is List ? ScriptTypes.ListString 34 | : value is List ? ScriptTypes.ListInteger 35 | : value is List ? ScriptTypes.ListDouble 36 | : value is List ? ScriptTypes.ListBoolean 37 | : ScriptTypes.Null; 38 | } 39 | 40 | public ScriptVariable(object value, ScriptTypes type) 41 | { 42 | Value = value; 43 | Type = type; 44 | } 45 | 46 | public ScriptVariable(string name, object value) 47 | { 48 | Name = name; 49 | Value = value; 50 | Type = value is string ? ScriptTypes.String 51 | : value is int ? ScriptTypes.Integer 52 | : value is double ? ScriptTypes.Double 53 | : value is bool ? ScriptTypes.Boolean 54 | : value is Regex ? ScriptTypes.Regex 55 | : value is List ? ScriptTypes.ListString 56 | : value is List ? ScriptTypes.ListInteger 57 | : value is List ? ScriptTypes.ListDouble 58 | : value is List ? ScriptTypes.ListBoolean 59 | : ScriptTypes.Null; 60 | } 61 | 62 | public ScriptVariable(string name, object value, ScriptTypes type) 63 | { 64 | Name = name; 65 | Value = value; 66 | Type = type; 67 | } 68 | 69 | public T Return() 70 | { 71 | var returnT = ScriptType.ToEnum(typeof(T)); 72 | switch (returnT) 73 | { 74 | case ScriptTypes.String: 75 | case ScriptTypes.Integer: 76 | case ScriptTypes.Double: 77 | case ScriptTypes.Boolean: 78 | case ScriptTypes.Regex: 79 | return (T)this.Value; 80 | case ScriptTypes.ListString: 81 | return (T)(object)((List)this.Value).Select(x => x.Value.ToString()).ToList(); 82 | case ScriptTypes.ListInteger: 83 | return (T)(object)((List)(this.Value)).Select(x => x).ToList(); 84 | case ScriptTypes.ListDouble: 85 | return (T)(object)((List)(this.Value)).Select(x => x).ToList(); 86 | case ScriptTypes.ListBoolean: 87 | return (T)(object)((List)(this.Value)).Select(x => x).ToList(); 88 | default: 89 | return default(T); 90 | } 91 | } 92 | 93 | public ScriptVariable Cast(Lexer lexer) 94 | { 95 | var outputType = ScriptType.ToEnum(typeof(ReturnT)); 96 | switch (outputType) 97 | { 98 | case ScriptTypes.String: 99 | switch (this.Type) 100 | { 101 | case ScriptTypes.Integer: 102 | case ScriptTypes.Double: 103 | this.Value = this.Value.ToString(); 104 | break; 105 | case ScriptTypes.Boolean: 106 | this.Value = (bool)this.Value ? "true" : "false"; 107 | break; 108 | case ScriptTypes.Null: 109 | this.Value = "null"; 110 | break; 111 | } 112 | this.Type = ScriptTypes.String; 113 | break; 114 | case ScriptTypes.Integer: 115 | switch (this.Type) 116 | { 117 | case ScriptTypes.String: 118 | int tryInt = 0; 119 | if (int.TryParse(this.Value.ToString(), out tryInt)) 120 | { 121 | this.Value = tryInt; 122 | } 123 | else 124 | { 125 | goto castError; 126 | } 127 | break; 128 | case ScriptTypes.Double: 129 | double tryDouble = 0; 130 | if (double.TryParse(this.Value.ToString(), out tryDouble)) 131 | { 132 | this.Value = tryDouble; 133 | } 134 | else 135 | { 136 | goto castError; 137 | } 138 | break; 139 | case ScriptTypes.Boolean: 140 | this.Value = (bool)this.Value ? 1 : 0; 141 | break; 142 | } 143 | this.Type = ScriptTypes.Integer; 144 | break; 145 | case ScriptTypes.Double: 146 | switch (this.Type) 147 | { 148 | case ScriptTypes.String: 149 | case ScriptTypes.Integer: 150 | double tryDouble = 0; 151 | if (double.TryParse(this.Value.ToString(), out tryDouble)) 152 | { 153 | this.Value = tryDouble; 154 | } 155 | else 156 | { 157 | goto castError; 158 | } 159 | break; 160 | case ScriptTypes.Boolean: 161 | this.Value = (bool)this.Value ? 1.0 : 0.0; 162 | break; 163 | } 164 | this.Type = ScriptTypes.Double; 165 | break; 166 | case ScriptTypes.Boolean: 167 | 168 | switch (this.Type) 169 | { 170 | case ScriptTypes.String: 171 | this.Value = this.Value.ToString() == "true"; 172 | break; 173 | } 174 | this.Type = ScriptTypes.Boolean; 175 | break; 176 | case ScriptTypes.ListString: 177 | case ScriptTypes.ListInteger: 178 | case ScriptTypes.ListDouble: 179 | case ScriptTypes.ListBoolean: 180 | 181 | break; 182 | case ScriptTypes.Void: 183 | this.Value = default(ReturnT); 184 | break; 185 | } 186 | return this; 187 | castError: 188 | lexer.Prev(); 189 | lexer.Prev(); 190 | throw new ScriptException( 191 | message: String.Format("Unable to cast value '{0}' from '{1}' to '{2}' on Line {3} Col {4}", 192 | Value.ToString(), 193 | Type.ToString(), 194 | outputType.ToString(), 195 | lexer.LineNumber, 196 | lexer.Position), 197 | row: lexer.LineNumber, 198 | column: lexer.Position, 199 | method: lexer.TokenContents 200 | ); 201 | } 202 | 203 | /*public ScriptVariable Cast(Lexer lexer) 204 | { 205 | var outputType = ScriptType.ToEnum(typeof(ReturnT)); 206 | var outValue = default(ReturnT); 207 | if (TryCast(Type, Value, out outValue)) 208 | { 209 | return this; 210 | } 211 | lexer.Prev(); 212 | lexer.Prev(); 213 | throw new ScriptException( 214 | message: String.Format("Unable to cast value '{0}' from '{1}' to '{2}' on Line {3} Col {4}", 215 | Value.ToString(), 216 | Type.ToString(), 217 | outputType.ToString(), 218 | lexer.LineNumber, 219 | lexer.Position), 220 | row: lexer.LineNumber, 221 | column: lexer.Position, 222 | method: lexer.TokenContents 223 | ); 224 | }*/ 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /Script/Script/TokenDefinitions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public static class TokenDefinitions 10 | { 11 | public static TokenDefinition Comment = new TokenDefinition(@"#.*", Tokens.Comment); 12 | public static TokenDefinition Regex = new TokenDefinition(@"/[^/]+/[ims]*", Tokens.Regex); 13 | public static TokenDefinition String = new TokenDefinition(@"([""'])(?:\\\1|.)*?\1", Tokens.String); 14 | public static TokenDefinition Integer = new TokenDefinition(@"[-+]?\d+", Tokens.Integer); 15 | public static TokenDefinition Double = new TokenDefinition(@"[-+]?\d*\.\d+", Tokens.Double); 16 | public static TokenDefinition Boolean = new TokenDefinition(@"(true|false)", Tokens.Boolean); 17 | public static TokenDefinition Null = new TokenDefinition(@"null", Tokens.Null); 18 | public static TokenDefinition If = new TokenDefinition(@"if\s?\(", Tokens.If); 19 | public static TokenDefinition ElseIf = new TokenDefinition(@"else if\s?\(", Tokens.ElseIf); 20 | public static TokenDefinition Else = new TokenDefinition(@"else", Tokens.Else); 21 | public static TokenDefinition For = new TokenDefinition(@"for\s?\(", Tokens.For); 22 | public static TokenDefinition Arithmetic = new TokenDefinition(@"(\+|-|\*|\/)", Tokens.Arithmetic); 23 | public static TokenDefinition ListType = new TokenDefinition(@"(var|int|double|string|bool)\[\]", Tokens.ListType); 24 | public static TokenDefinition BaseType = new TokenDefinition(@"(var|int|double|string|bool)", Tokens.BaseType); 25 | public static TokenDefinition Keyword = new TokenDefinition(@"(name|extends|event|function|string|integer|double|boolean|array|return)", Tokens.Keyword); 26 | public static TokenDefinition Symbol = new TokenDefinition(@"[*<>\?\-+/A-Za-z->!][*<>\?\-+/A-Za-z0-9->!]*", Tokens.Symbol); 27 | public static TokenDefinition ArrayLeft = new TokenDefinition(@"\[", Tokens.ArrayLeft); 28 | public static TokenDefinition ArrayRight = new TokenDefinition(@"\]", Tokens.ArrayRight); 29 | public static TokenDefinition Dot = new TokenDefinition(@"\.", Tokens.Dot); 30 | public static TokenDefinition Comma = new TokenDefinition(@",", Tokens.Comma); 31 | public static TokenDefinition Left = new TokenDefinition(@"\(", Tokens.Left); 32 | public static TokenDefinition Right = new TokenDefinition(@"\)", Tokens.Right); 33 | public static TokenDefinition Assignment = new TokenDefinition(@"(=|\+=|-=|\*=|\\=)", Tokens.Assignment); 34 | public static TokenDefinition Operator = new TokenDefinition(@" (and|or) ", Tokens.Operator); 35 | public static TokenDefinition Tab = new TokenDefinition(@"[ ]{4}", Tokens.Tab); 36 | public static TokenDefinition Space = new TokenDefinition(@"[ ]+", Tokens.Space); 37 | public static TokenDefinition Event = new TokenDefinition(@"event[ ]+[*<>\?\-+/A-Za-z->!][*<>\?\-+/A-Za-z0-9->!]*", Tokens.Event); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Script/Script/Tokens.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Script 8 | { 9 | public enum Tokens 10 | { 11 | Block, 12 | Comment, 13 | Regex, 14 | String, 15 | Double, 16 | Integer, 17 | Boolean, 18 | Null, 19 | If, 20 | ElseIf, 21 | Else, 22 | For, 23 | Arithmetic, 24 | ListType, 25 | BaseType, 26 | Keyword, 27 | Symbol, 28 | ArrayLeft, 29 | ArrayRight, 30 | Dot, 31 | Comma, 32 | Left, 33 | Right, 34 | Assignment, 35 | Operator, 36 | Tab, 37 | Space, 38 | Arguments, 39 | Parameters, 40 | EventName, 41 | EventNameParameters, 42 | Event, 43 | Function, 44 | Code 45 | } 46 | } -------------------------------------------------------------------------------- /Script/ScriptTest/ArithmeticInteger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace ScriptTest 8 | { 9 | [TestClass] 10 | public class ArithmeticInteger 11 | { 12 | 13 | [TestMethod] 14 | public void ArithmeticIntegerAddString() 15 | { 16 | var script = new ScriptEngine(); 17 | script.Exception(e => 18 | { 19 | Assert.Fail(e.Message); 20 | }); 21 | Assert.AreEqual("40text", script.Evaluate("40 + 'text'")); 22 | } 23 | 24 | [TestMethod] 25 | public void ArithmeticIntegerMinusString() 26 | { 27 | var script = new ScriptEngine(); 28 | script.Exception(e => 29 | { 30 | Assert.AreEqual("Unable to cast value 'text' from 'String' to 'Double' on Line 1 Col 5", e.Message); 31 | }); 32 | script.Execute("40 - 'text'"); 33 | } 34 | 35 | [TestMethod] 36 | public void ArithmeticIntegerMultiplyString() 37 | { 38 | var script = new ScriptEngine(); 39 | script.Exception(e => 40 | { 41 | Assert.AreEqual("Unable to cast value 'text' from 'String' to 'Double' on Line 1 Col 5", e.Message); 42 | }); 43 | script.Execute("40 * 'text'"); 44 | } 45 | 46 | [TestMethod] 47 | public void ArithmeticIntegerDivideString() 48 | { 49 | var script = new ScriptEngine(); 50 | script.Exception(e => 51 | { 52 | Assert.AreEqual("Unable to cast value 'text' from 'String' to 'Double' on Line 1 Col 5", e.Message); 53 | }); 54 | script.Execute("40 / 'text'"); 55 | } 56 | 57 | [TestMethod] 58 | public void ArithmeticIntegerAddInteger() 59 | { 60 | var script = new ScriptEngine(); 61 | script.Exception(e => 62 | { 63 | Assert.Fail(e.Message); 64 | }); 65 | Assert.AreEqual(42, script.Evaluate("40 + 2")); 66 | } 67 | 68 | [TestMethod] 69 | public void ArithmeticIntegerMinusInteger() 70 | { 71 | var script = new ScriptEngine(); 72 | script.Exception(e => 73 | { 74 | Assert.Fail(e.Message); 75 | }); 76 | Assert.AreEqual(38, script.Evaluate("40 - 2")); 77 | } 78 | 79 | [TestMethod] 80 | public void ArithmeticIntegerMultiplyInteger() 81 | { 82 | var script = new ScriptEngine(); 83 | script.Exception(e => 84 | { 85 | Assert.Fail(e.Message); 86 | }); 87 | Assert.AreEqual(80, script.Evaluate("40 * 2")); 88 | } 89 | 90 | [TestMethod] 91 | public void ArithmeticIntegerDivideInterger() 92 | { 93 | var script = new ScriptEngine(); 94 | script.Exception(e => 95 | { 96 | Assert.Fail(e.Message); 97 | }); 98 | Assert.AreEqual(20.0, script.Evaluate("40 / 2")); 99 | } 100 | 101 | [TestMethod] 102 | public void ArithmeticIntegerAddDouble() 103 | { 104 | var script = new ScriptEngine(); 105 | script.Exception(e => 106 | { 107 | Assert.Fail(e.Message); 108 | }); 109 | Assert.AreEqual(42.0, script.Evaluate("40 + 2.0")); 110 | } 111 | 112 | [TestMethod] 113 | public void ArithmeticIntegerMinusDouble() 114 | { 115 | var script = new ScriptEngine(); 116 | script.Exception(e => 117 | { 118 | Assert.Fail(e.Message); 119 | }); 120 | Assert.AreEqual(38.0, script.Evaluate("40 - 2.0")); 121 | } 122 | 123 | [TestMethod] 124 | public void ArithmeticIntegerMultiplyDouble() 125 | { 126 | var script = new ScriptEngine(); 127 | script.Exception(e => 128 | { 129 | Assert.Fail(e.Message); 130 | }); 131 | Assert.AreEqual(80.0, script.Evaluate("40 * 2.0")); 132 | } 133 | 134 | [TestMethod] 135 | public void ArithmeticIntegerDivideDouble() 136 | { 137 | var script = new ScriptEngine(); 138 | script.Exception(e => 139 | { 140 | Assert.Fail(e.Message); 141 | }); 142 | Assert.AreEqual(20.0, script.Evaluate("40 / 2.0")); 143 | } 144 | 145 | [TestMethod] 146 | public void ArithmeticIntegerAddListString() 147 | { 148 | var script = new ScriptEngine(); 149 | script.Exception(e => 150 | { 151 | Assert.Fail(e.Message); 152 | }); 153 | Assert.AreEqual("40hello,world,!", script.Evaluate("40 + ['hello', 'world', '!']")); 154 | } 155 | 156 | [TestMethod] 157 | public void ArithmeticVariableIntegerAddInteger() 158 | { 159 | var script = new ScriptEngine(); 160 | var code = new StringBuilder(); 161 | code.AppendLine("int foo = 40"); 162 | code.AppendLine("foo + 2"); 163 | Assert.AreEqual(42, script.Evaluate(code.ToString())); 164 | } 165 | 166 | [TestMethod] 167 | public void ArithmeticVariableIntegerAddString() 168 | { 169 | var script = new ScriptEngine(); 170 | var code = new StringBuilder(); 171 | code.AppendLine("int foo = 40"); 172 | code.AppendLine("foo + '2'"); 173 | Assert.AreEqual("402", script.Evaluate(code.ToString())); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /Script/ScriptTest/Cast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Text; 5 | 6 | namespace ScriptTest 7 | { 8 | [TestClass] 9 | public class Cast 10 | { 11 | [TestMethod] 12 | public void CastStringToString() 13 | { 14 | var script = new ScriptEngine(); 15 | Assert.AreEqual("Test", script.Evaluate("string('Test')")); 16 | } 17 | 18 | [TestMethod] 19 | public void CastIntToString() 20 | { 21 | var script = new ScriptEngine(); 22 | Assert.AreEqual("4", script.Evaluate("string(4)")); 23 | Assert.AreEqual("42", script.Evaluate("string(42)")); 24 | } 25 | 26 | [TestMethod] 27 | public void CastDoubleToString() 28 | { 29 | var script = new ScriptEngine(); 30 | Assert.AreEqual("4", script.Evaluate("string(4.0)")); 31 | Assert.AreEqual("4.2", script.Evaluate("string(4.2)")); 32 | Assert.AreEqual("4.2", script.Evaluate("string(4.20)")); 33 | } 34 | 35 | [TestMethod] 36 | public void CastBoolToString() 37 | { 38 | var script = new ScriptEngine(); 39 | Assert.AreEqual("true", script.Evaluate("string(true)")); 40 | Assert.AreEqual("false", script.Evaluate("string(false)")); 41 | } 42 | 43 | [TestMethod] 44 | public void CastNullToString() 45 | { 46 | var script = new ScriptEngine(); 47 | Assert.AreEqual("null", script.Evaluate("string(null)")); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Script/ScriptTest/Condition.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class Condition 13 | { 14 | 15 | [TestMethod] 16 | public void ConditionBoolTrue() 17 | { 18 | var script = new ScriptEngine(); 19 | script.AddAction("log", message => 20 | { 21 | Assert.AreEqual("Hello World!", message); 22 | }); 23 | var code = new StringBuilder(); 24 | code.AppendLine("if (true)"); // Basic if statment 25 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 26 | script.Execute(code.ToString()); 27 | } 28 | 29 | [TestMethod] 30 | public void ConditionBoolFalse() 31 | { 32 | var script = new ScriptEngine(); 33 | script.AddAction("log", message => 34 | { 35 | Assert.Fail("This should never be called."); 36 | }); 37 | var code = new StringBuilder(); 38 | code.AppendLine("if (false)"); // Basic if statment 39 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 40 | script.Execute(code.ToString()); 41 | } 42 | 43 | [TestMethod] 44 | public void ConditionFunctionBoolTrue() 45 | { 46 | var script = new ScriptEngine(); 47 | script.AddCondition("foo", message => { 48 | return "bar" == message; 49 | }); 50 | script.AddAction("log", message => 51 | { 52 | Assert.AreEqual("Hello World!", message); 53 | }); 54 | var code = new StringBuilder(); 55 | code.AppendLine("if (foo('bar'))"); // Basic if statment 56 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 57 | script.Execute(code.ToString()); 58 | } 59 | 60 | [TestMethod] 61 | public void ConditionFunctionBoolFalse() 62 | { 63 | var script = new ScriptEngine(); 64 | script.AddCondition("foo", message => 65 | { 66 | return "bar" == message; 67 | }); 68 | script.AddAction("log", message => 69 | { 70 | Assert.Fail("This should never be called."); 71 | }); 72 | var code = new StringBuilder(); 73 | code.AppendLine("if (foo('blarg'))"); // Basic if statment 74 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 75 | script.Execute(code.ToString()); 76 | } 77 | 78 | [TestMethod] 79 | public void ConditionBoolTrueAndTrue() 80 | { 81 | var script = new ScriptEngine(); 82 | script.AddCondition("foo", message => 83 | { 84 | return "bar" == message; 85 | }); 86 | script.AddAction("log", message => 87 | { 88 | Assert.AreEqual("Hello World!", message); 89 | }); 90 | var code = new StringBuilder(); 91 | code.AppendLine("if (foo('bar') and foo('bar'))"); // Basic if statment 92 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 93 | script.Execute(code.ToString()); 94 | } 95 | 96 | [TestMethod] 97 | public void ConditionBoolTrueAndFalse() 98 | { 99 | var script = new ScriptEngine(); 100 | script.AddCondition("foo", message => 101 | { 102 | return "bar" == message; 103 | }); 104 | script.AddAction("log", message => 105 | { 106 | Assert.Fail("This should never be called."); 107 | }); 108 | var code = new StringBuilder(); 109 | code.AppendLine("if (foo('bar') and foo('blarg'))"); // Basic if statment 110 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 111 | script.Execute(code.ToString()); 112 | } 113 | 114 | [TestMethod] 115 | public void ConditionBoolTrueOrFalse() 116 | { 117 | var script = new ScriptEngine(); 118 | script.AddCondition("foo", message => 119 | { 120 | return "bar" == message; 121 | }); 122 | script.AddAction("log", message => 123 | { 124 | Assert.AreEqual("Hello World!", message); 125 | }); 126 | var code = new StringBuilder(); 127 | code.AppendLine("if (foo('bar') or foo('blarg'))"); // Basic if statment 128 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 129 | script.Execute(code.ToString()); 130 | } 131 | 132 | [TestMethod] 133 | public void ConditionBoolFalseOrFalse() 134 | { 135 | var script = new ScriptEngine(); 136 | script.Exception(ExceptionHandler); 137 | script.AddCondition("foo", message => 138 | { 139 | return "bar" == message; 140 | }); 141 | script.AddAction("log", message => 142 | { 143 | Assert.Fail("This should never be called."); 144 | }); 145 | var code = new StringBuilder(); 146 | code.AppendLine("if (foo('fail1') and foo('fail2'))"); // Basic if statment 147 | code.AppendLine(" log('Hello World!')"); // Should run log, pass { indent: 1 } 148 | script.Execute(code.ToString()); 149 | } 150 | 151 | private void ExceptionHandler(ScriptException error) 152 | { 153 | Assert.Fail(); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Script/ScriptTest/ConditionElse.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class ConditionElse 13 | { 14 | [TestMethod] 15 | public void ConditionElseBoolTrue() 16 | { 17 | var script = new ScriptEngine(); 18 | script.AddCondition("foo", message => 19 | { 20 | return "bar" == message; 21 | }); 22 | script.AddAction("log", message => 23 | { 24 | Assert.AreEqual("Hello World!", message); 25 | }); 26 | var code = new StringBuilder(); 27 | code.AppendLine("if (foo('bar'))"); // Basic if statment 28 | code.AppendLine(" log('Hello World!')"); 29 | code.AppendLine("else"); 30 | code.AppendLine(" log('Goodbye World!')"); 31 | script.Execute(code.ToString()); 32 | } 33 | 34 | [TestMethod] 35 | public void ConditionElseBoolFalse() 36 | { 37 | var script = new ScriptEngine(); 38 | script.AddCondition("foo", message => 39 | { 40 | return "bar" == message; 41 | }); 42 | script.AddAction("log", message => 43 | { 44 | Assert.AreEqual("Hello World!", message); 45 | }); 46 | var code = new StringBuilder(); 47 | code.AppendLine("if (foo('blarg'))"); // Basic if statment 48 | code.AppendLine(" log('Goodbye World!')"); 49 | code.AppendLine("else"); 50 | code.AppendLine(" log('Hello World!')"); 51 | script.Execute(code.ToString()); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Script/ScriptTest/ConditionIfElse.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class ConditionIfElse 13 | { 14 | [TestMethod] 15 | public void ConditionIfElseBoolTrue() 16 | { 17 | var script = new ScriptEngine(); 18 | script.AddCondition("foo", message => 19 | { 20 | return "bar" == message; 21 | }); 22 | script.AddAction("log", message => 23 | { 24 | Assert.AreEqual("Hello World!", message); 25 | }); 26 | var code = new StringBuilder(); 27 | code.AppendLine("if (foo('bar'))"); // Basic if statment 28 | code.AppendLine(" log('Hello World!')"); 29 | code.AppendLine("else if (foo('blarg'))"); 30 | code.AppendLine(" log('Goodbye World!')"); 31 | script.Execute(code.ToString()); 32 | } 33 | 34 | [TestMethod] 35 | public void ConditionIfElseBoolFalse() 36 | { 37 | var script = new ScriptEngine(); 38 | script.AddCondition("foo", message => 39 | { 40 | return "bar" == message; 41 | }); 42 | script.AddAction("log", message => 43 | { 44 | Assert.AreEqual("Hello World!", message); 45 | }); 46 | var code = new StringBuilder(); 47 | code.AppendLine("if (foo('blarg'))"); // Basic if statment 48 | code.AppendLine(" log('Goodbye World!')"); 49 | code.AppendLine("else if (foo('bar'))"); 50 | code.AppendLine(" log('Hello World!')"); 51 | script.Execute(code.ToString()); 52 | } 53 | 54 | [TestMethod] 55 | public void ConditionIfElseElseBoolFalse() 56 | { 57 | var script = new ScriptEngine(); 58 | script.AddCondition("foo", message => 59 | { 60 | return "bar" == message; 61 | }); 62 | script.AddAction("log", message => 63 | { 64 | Assert.AreEqual("Hello World!", message); 65 | }); 66 | var code = new StringBuilder(); 67 | code.AppendLine("if (foo('blarg'))"); // Basic if statment 68 | code.AppendLine(" log('Goodbye World!')"); 69 | code.AppendLine("else if (foo('blarg'))"); 70 | code.AppendLine(" log('Goodbye World!')"); 71 | code.AppendLine("else"); 72 | code.AppendLine(" log('Hello World!')"); 73 | script.Execute(code.ToString()); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Script/ScriptTest/Debug.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace ScriptTest 8 | { 9 | [TestClass] 10 | public class Debug 11 | { 12 | 13 | [TestMethod] 14 | public void DebugLogString() 15 | { 16 | var script = new ScriptEngine(); 17 | var debugClass = script.AddClass("debug"); 18 | debugClass.AddAction("log", message => 19 | { 20 | Assert.AreEqual("Hello World!", message); 21 | }); 22 | script.Execute("debug.log('Hello World!')"); 23 | } 24 | 25 | [TestMethod] 26 | public void DebugLogInteger() 27 | { 28 | var script = new ScriptEngine(); 29 | var debugClass = script.AddClass("debug"); 30 | debugClass.AddAction("log", message => 31 | { 32 | Assert.AreEqual(42, message); 33 | }); 34 | script.Execute("debug.log(42)"); 35 | } 36 | 37 | [TestMethod] 38 | public void DebugLogDouble() 39 | { 40 | var script = new ScriptEngine(); 41 | var debugClass = script.AddClass("debug"); 42 | debugClass.AddAction("log", message => 43 | { 44 | Assert.AreEqual(4.2, message); 45 | }); 46 | script.Execute("debug.log(4.2)"); 47 | } 48 | 49 | [TestMethod] 50 | public void DebugLogBoolean() 51 | { 52 | var script = new ScriptEngine(); 53 | var debugClass = script.AddClass("debug"); 54 | debugClass.AddAction("log", message => 55 | { 56 | Assert.AreEqual(true, message); 57 | }); 58 | script.Execute("debug.log(true)"); 59 | } 60 | 61 | [TestMethod] 62 | public void DebugLogArray() 63 | { 64 | var script = new ScriptEngine(); 65 | var debugClass = script.AddClass("debug"); 66 | debugClass.AddAction>("log", message => 67 | { 68 | Assert.AreEqual("Hello World!", message[0]); 69 | }); 70 | script.Exception(e => 71 | { 72 | Assert.Fail(e.Message); 73 | }); 74 | script.Execute("debug.log(['Hello World!'])"); 75 | } 76 | 77 | [TestMethod] 78 | public void DebugLogSetList() 79 | { 80 | var script = new ScriptEngine(); 81 | script.Exception(e => 82 | { 83 | Assert.Fail(e.Message); 84 | }); 85 | var code = new StringBuilder(); 86 | code.AppendLine("string[] foo = ['Hello', 'World!']"); 87 | code.AppendLine("foo"); 88 | var value = script.Evaluate>(code.ToString()); 89 | Assert.AreEqual(value[0], "Hello"); 90 | } 91 | 92 | [TestMethod] 93 | public void DebugLogSetListNull() 94 | { 95 | var script = new ScriptEngine(); 96 | script.Exception(e => 97 | { 98 | Assert.Fail(e.Message); 99 | }); 100 | var code = new StringBuilder(); 101 | code.AppendLine("string[] foo = []"); 102 | code.AppendLine("foo"); 103 | var value = script.Evaluate>(code.ToString()); 104 | Assert.AreEqual(value.Count, 0); 105 | } 106 | 107 | [TestMethod] 108 | public void ListStringAndRead() 109 | { 110 | var script = new ScriptEngine(); 111 | script.Exception(e => 112 | { 113 | Assert.Fail(e.Message); 114 | }); 115 | var code = new StringBuilder(); 116 | code.AppendLine("string[] foo = ['Hello', 'World!']"); 117 | code.AppendLine("foo[0]"); 118 | var value = script.Evaluate(code.ToString()); 119 | Assert.AreEqual(value, "Hello"); 120 | } 121 | 122 | [TestMethod] 123 | public void ListStringNestedAndRead() 124 | { 125 | // Nested arrays are not supported. 126 | var script = new ScriptEngine(); 127 | script.Exception(e => 128 | { 129 | Assert.AreEqual("Invalid data type 'ListString' in 'String' list near Line 1 Col 36", e.Message); 130 | }); 131 | var code = new StringBuilder(); 132 | code.AppendLine("string[] foo = [['Hello', 'Again'], 'World!']"); 133 | code.AppendLine("foo[0][0]"); 134 | var value = script.Evaluate(code.ToString()); 135 | Assert.AreNotEqual(value, "Hello"); 136 | } 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Script/ScriptTest/Evaluate.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class Evaluate 13 | { 14 | [TestMethod] 15 | public void EvaluateString() 16 | { 17 | var script = new ScriptEngine(); 18 | script.AddFunction("append", message => 19 | { 20 | return message + " World!"; 21 | }); 22 | var code = new StringBuilder(); 23 | code.AppendLine("return append('Hello')"); // Should run log, pass { indent: 1 } 24 | Assert.AreEqual("Hello World!", script.Evaluate(code.ToString())); 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Script/ScriptTest/Execute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class Execute 13 | { 14 | [TestMethod] 15 | public void ExecuteBasic() 16 | { 17 | var script = new ScriptEngine(); 18 | script.AddAction("log", message => 19 | { 20 | Assert.AreEqual("Hello World!", message); 21 | }); 22 | var code = new StringBuilder(); 23 | code.AppendLine("log('Hello World!')"); // Should run log, pass { indent: 1 } 24 | script.Execute(code.ToString()); 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Script/ScriptTest/ExecuteOverload.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class ExecuteOverloads 13 | { 14 | [TestMethod] 15 | public void ExecuteOverload() 16 | { 17 | var script = new ScriptEngine(); 18 | script.AddAction("log", message => 19 | { 20 | Assert.AreEqual("Hello World!", message); 21 | }); 22 | script.AddAction("log", (message1, message2) => 23 | { 24 | Assert.AreEqual("Hello World!", message1 + " " + message2); 25 | }); 26 | var code = new StringBuilder(); 27 | code.AppendLine("log('Hello World!')"); // Should run log, pass { indent: 1 } 28 | code.AppendLine("log('Hello', 'World!')"); // Should run log, pass { indent: 1 } 29 | script.Execute(code.ToString()); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Script/ScriptTest/Extend.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Text; 5 | using System.Collections.Generic; 6 | 7 | namespace ScriptTest 8 | { 9 | [TestClass] 10 | public class Extend 11 | { 12 | [TestMethod] 13 | public void TypeFunctionStringArrayJoin() 14 | { 15 | var script = new ScriptEngine(); 16 | script.TypeFunction, string, string>("join", (list, separator) => 17 | { 18 | return string.Join(separator, list.ToArray()); 19 | }); 20 | var code = new StringBuilder(); 21 | code.AppendLine("string[] foo = ['foo', 'bar']"); 22 | code.AppendLine("foo.join('-')"); 23 | Assert.AreEqual("foo-bar", script.Evaluate(code.ToString())); 24 | } 25 | 26 | [TestMethod] 27 | public void TypeFunctionStringArrayJoinOverload() 28 | { 29 | var script = new ScriptEngine(); 30 | script.TypeFunction, string>("join", (list) => 31 | { 32 | return string.Join(",", list.ToArray()); 33 | }); 34 | script.TypeFunction, string, string>("join", (list, separator) => 35 | { 36 | return string.Join(separator, list.ToArray()); 37 | }); 38 | var code = new StringBuilder(); 39 | code.AppendLine("string[] foo = ['foo', 'bar']"); 40 | code.AppendLine("foo.join('-')"); 41 | Assert.AreEqual("foo-bar", script.Evaluate(code.ToString())); 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Script/ScriptTest/ForLoop.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class ForLoop 13 | { 14 | 15 | [TestMethod] 16 | public void ConditionBoolTrue() 17 | { 18 | var script = new ScriptEngine(); 19 | script.AddAction("log", message => 20 | { 21 | Assert.IsTrue(message == "test1" || message == "test2"); 22 | }); 23 | var code = new StringBuilder(); 24 | code.AppendLine("for (var i in ['test1', 'test2'])"); // Basic if statment 25 | code.AppendLine(" log(i)"); // Should run log, pass { indent: 1 } 26 | script.Execute(code.ToString()); 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Script/ScriptTest/Function.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Text; 5 | 6 | namespace ScriptTest 7 | { 8 | [TestClass] 9 | public class Function 10 | { 11 | [TestMethod] 12 | public void FunctionString() 13 | { 14 | var script = new ScriptEngine(); 15 | var debugClass = script.AddClass("debug"); 16 | debugClass.AddAction("log", message => 17 | { 18 | Assert.AreEqual("Hello World!", message); 19 | }); 20 | script.Execute("debug.log('Hello World!')"); 21 | } 22 | 23 | [TestMethod] 24 | public void FunctionInvalidArguments() 25 | { 26 | var script = new ScriptEngine(); 27 | script.AddAction("log", message => 28 | { 29 | Assert.Fail(); 30 | }); 31 | script.Exception(e => 32 | { 33 | Assert.AreEqual("Unexpected string on Line 1 Col 14", e.Message); 34 | }); 35 | script.Execute("log('Missing' 'Comma!')"); 36 | } 37 | 38 | [TestMethod] 39 | public void FunctionVariableString() 40 | { 41 | var script = new ScriptEngine(); 42 | script.AddFunction("appendWorld", message => 43 | { 44 | return message + " World!"; 45 | }); 46 | var code = new StringBuilder(); 47 | code.AppendLine("string foo = 'Hello'"); 48 | code.AppendLine("appendWorld(foo)"); // Should run log, pass { indent: 1 } 49 | Assert.AreEqual("Hello World!", script.Evaluate(code.ToString())); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Script/ScriptTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScriptTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ScriptTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9c9d0020-d29c-44e3-a814-72227eb3424e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Script/ScriptTest/Property.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Text; 5 | 6 | namespace ScriptTest 7 | { 8 | [TestClass] 9 | public class Property 10 | { 11 | [TestMethod] 12 | public void PropertyString() 13 | { 14 | var script = new ScriptEngine(); 15 | var test = script.AddClass("Test"); 16 | test.AddProperty("test", "Hello World!"); 17 | Assert.AreEqual("Hello World!", script.Evaluate("Test.test")); 18 | } 19 | 20 | [TestMethod] 21 | public void PropertyInteger() 22 | { 23 | var script = new ScriptEngine(); 24 | var test = script.AddClass("Test"); 25 | test.AddProperty("test", 10); 26 | Assert.AreEqual(10, script.Evaluate("Test.test")); 27 | } 28 | 29 | [TestMethod] 30 | public void PropertyDouble() 31 | { 32 | var script = new ScriptEngine(); 33 | var test = script.AddClass("Test"); 34 | test.AddProperty("test", 10.0); 35 | Assert.AreEqual(10.0, script.Evaluate("Test.test")); 36 | } 37 | 38 | [TestMethod] 39 | public void PropertyBoolTrue() 40 | { 41 | var script = new ScriptEngine(); 42 | var test = script.AddClass("Test"); 43 | test.AddProperty("test", true); 44 | Assert.AreEqual(true, script.Evaluate("Test.test")); 45 | } 46 | 47 | [TestMethod] 48 | public void PropertyBoolFalse() 49 | { 50 | var script = new ScriptEngine(); 51 | var test = script.AddClass("Test"); 52 | test.AddProperty("test", false); 53 | Assert.AreEqual(false, script.Evaluate("Test.test")); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Script/ScriptTest/RegexBasic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Collections.Generic; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace ScriptTest 8 | { 9 | [TestClass] 10 | public class RegexBasic 11 | { 12 | [TestMethod] 13 | public void RegexParameter() 14 | { 15 | var script = new ScriptEngine(); 16 | script.TypeFunction>("match", (value, regex) => 17 | { 18 | Match m = regex.Match(value); 19 | if (m.Success) 20 | { 21 | return new List() { m.Value }; 22 | } 23 | else 24 | { 25 | return new List(); 26 | } 27 | }); 28 | var val = script.Evaluate>("'footestfoo'.match(/test/)"); 29 | Assert.AreEqual(1, val.Count); 30 | Assert.AreEqual("test", val[0]); 31 | } 32 | 33 | [TestMethod] 34 | public void RegexParameterIgnoreCase() 35 | { 36 | var script = new ScriptEngine(); 37 | script.TypeFunction>("match", (value, regex) => 38 | { 39 | Match m = regex.Match(value); 40 | if (m.Success) 41 | { 42 | return new List() { m.Value }; 43 | } 44 | else 45 | { 46 | return new List(); 47 | } 48 | }); 49 | var val = script.Evaluate>("'fooTestfoo'.match(/test/i)"); 50 | Assert.AreEqual(1, val.Count); 51 | Assert.AreEqual("Test", val[0]); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Script/ScriptTest/ScriptTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {9E90A7D0-5268-4267-B607-01C6341299B4} 7 | Library 8 | Properties 9 | ScriptTest 10 | ScriptTest 11 | v4.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | False 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {e8c08c44-303e-4f2c-98cc-e22dbac85c60} 76 | Script 77 | 78 | 79 | 80 | 81 | 82 | 83 | False 84 | 85 | 86 | False 87 | 88 | 89 | False 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | 98 | 99 | 106 | -------------------------------------------------------------------------------- /Script/ScriptTest/Trigger.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Script; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ScriptTest 10 | { 11 | [TestClass] 12 | public class Trigger 13 | { 14 | [TestMethod] 15 | public void TriggerBasic() 16 | { 17 | var script = new ScriptEngine(); 18 | script.AddAction("log1", message => 19 | { 20 | Assert.AreEqual("Hello World 1!", message); 21 | }); 22 | script.AddAction("log2", message => 23 | { 24 | Assert.AreEqual("Hello World 2!", message); 25 | }); 26 | script.AddAction("log", message => 27 | { 28 | Assert.Fail(); 29 | }); 30 | var code = new StringBuilder(); 31 | code.AppendLine("event action"); 32 | code.AppendLine(" log1('Hello World 1!')"); 33 | code.AppendLine(" log2('Hello World 2!')"); 34 | code.AppendLine("event foo"); 35 | code.AppendLine(" log('Goodbye World!')"); 36 | script.Process(code.ToString()); 37 | script.Trigger("action"); 38 | } 39 | 40 | [TestMethod] 41 | public void TriggerFunction() 42 | { 43 | var script = new ScriptEngine(); 44 | script.AddAction("log1", message => 45 | { 46 | Assert.AreEqual(10, message); 47 | }); 48 | script.AddAction("log2", message => 49 | { 50 | Assert.Fail(); 51 | }); 52 | var code = new StringBuilder(); 53 | code.AppendLine("event drop(item)"); 54 | code.AppendLine(" log1(item)"); 55 | code.AppendLine("event foo"); 56 | code.AppendLine(" log2('Goodbye World!')"); 57 | script.Process(code.ToString()); 58 | script.Trigger("drop", 10); 59 | } 60 | 61 | [TestMethod] 62 | public void TriggerUndefined() 63 | { 64 | var script = new ScriptEngine(); 65 | script.AddAction("log1", message => 66 | { 67 | Assert.AreEqual("Hello World 1!", message); 68 | }); 69 | script.AddAction("log2", message => 70 | { 71 | Assert.AreEqual("Hello World 2!", message); 72 | }); 73 | script.AddAction("log", message => 74 | { 75 | Assert.Fail(); 76 | }); 77 | var code = new StringBuilder(); 78 | code.AppendLine("event action"); 79 | code.AppendLine(" log1('Hello World 1!')"); 80 | code.AppendLine(" log2('Hello World 2!')"); 81 | code.AppendLine("event foo"); 82 | code.AppendLine(" log('Goodbye World!')"); 83 | script.Process(code.ToString()); 84 | script.Trigger("test"); 85 | } 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Script/ScriptTest/Variable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Script; 4 | using System.Text; 5 | 6 | namespace ScriptTest 7 | { 8 | [TestClass] 9 | public class Variable 10 | { 11 | [TestMethod] 12 | public void VariableString() 13 | { 14 | var script = new ScriptEngine(); 15 | var code = new StringBuilder(); 16 | code.AppendLine("string foo = 'Hello World!'"); 17 | code.AppendLine("foo"); 18 | Assert.AreEqual("Hello World!", script.Evaluate(code.ToString())); 19 | } 20 | 21 | [TestMethod] 22 | public void VariableInteger() 23 | { 24 | var script = new ScriptEngine(); 25 | var code = new StringBuilder(); 26 | code.AppendLine("int foo = 10"); 27 | code.AppendLine("foo"); 28 | Assert.AreEqual(10, script.Evaluate(code.ToString())); 29 | } 30 | 31 | [TestMethod] 32 | public void VariableDouble() 33 | { 34 | var script = new ScriptEngine(); 35 | var code = new StringBuilder(); 36 | code.AppendLine("double foo = 2.0"); 37 | code.AppendLine("foo"); 38 | Assert.AreEqual(2.0, script.Evaluate(code.ToString())); 39 | } 40 | 41 | [TestMethod] 42 | public void VariableBoolTrue() 43 | { 44 | var script = new ScriptEngine(); 45 | var code = new StringBuilder(); 46 | code.AppendLine("bool foo = true"); 47 | code.AppendLine("foo"); 48 | Assert.AreEqual(true, script.Evaluate(code.ToString())); 49 | } 50 | 51 | [TestMethod] 52 | public void VariableBoolFalse() 53 | { 54 | var script = new ScriptEngine(); 55 | var code = new StringBuilder(); 56 | code.AppendLine("bool foo = false"); 57 | code.AppendLine("foo"); 58 | Assert.AreEqual(false, script.Evaluate(code.ToString())); 59 | } 60 | 61 | [TestMethod] 62 | public void VariableVarString() 63 | { 64 | var script = new ScriptEngine(); 65 | var code = new StringBuilder(); 66 | code.AppendLine("var foo = 'Hello World!'"); 67 | code.AppendLine("foo"); 68 | Assert.AreEqual("Hello World!", script.Evaluate(code.ToString())); 69 | } 70 | 71 | [TestMethod] 72 | public void VariableVarInteger() 73 | { 74 | var script = new ScriptEngine(); 75 | var code = new StringBuilder(); 76 | code.AppendLine("var foo = 10"); 77 | code.AppendLine("foo"); 78 | Assert.AreEqual(10, script.Evaluate(code.ToString())); 79 | } 80 | 81 | [TestMethod] 82 | public void VariableVarDouble() 83 | { 84 | var script = new ScriptEngine(); 85 | var code = new StringBuilder(); 86 | code.AppendLine("var foo = 2.0"); 87 | code.AppendLine("foo"); 88 | Assert.AreEqual(2.0, script.Evaluate(code.ToString())); 89 | } 90 | 91 | [TestMethod] 92 | public void VariableVarBoolTrue() 93 | { 94 | var script = new ScriptEngine(); 95 | var code = new StringBuilder(); 96 | code.AppendLine("var foo = true"); 97 | code.AppendLine("foo"); 98 | Assert.AreEqual(true, script.Evaluate(code.ToString())); 99 | } 100 | 101 | [TestMethod] 102 | public void VariableVarBoolFalse() 103 | { 104 | var script = new ScriptEngine(); 105 | var code = new StringBuilder(); 106 | code.AppendLine("var foo = false"); 107 | code.AppendLine("foo"); 108 | Assert.AreEqual(false, script.Evaluate(code.ToString())); 109 | } 110 | 111 | [TestMethod] 112 | public void VariableStringToInt() 113 | { 114 | var script = new ScriptEngine(); 115 | var code = new StringBuilder(); 116 | script.Exception(error => 117 | { 118 | Assert.AreEqual("String 'foo' set to Integer on Line 1 Col 13", error.Message); 119 | }); 120 | code.AppendLine("string foo = 4"); 121 | code.AppendLine("foo"); 122 | script.Execute(code.ToString()); 123 | } 124 | 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptDemo", "ScriptDemo\ScriptDemo.csproj", "{E390EC83-B1A0-4AD5-BCAB-81764D7BA538}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script", "..\Script\Script\Script.csproj", "{E8C08C44-303E-4F2C-98CC-E22DBAC85C60}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|ARM = Release|ARM 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|Any CPU.ActiveCfg = Debug|x86 23 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|ARM.ActiveCfg = Debug|ARM 24 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|ARM.Build.0 = Debug|ARM 25 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|ARM.Deploy.0 = Debug|ARM 26 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|x64.ActiveCfg = Debug|x64 27 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|x64.Build.0 = Debug|x64 28 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|x64.Deploy.0 = Debug|x64 29 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|x86.ActiveCfg = Debug|x86 30 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|x86.Build.0 = Debug|x86 31 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Debug|x86.Deploy.0 = Debug|x86 32 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|Any CPU.ActiveCfg = Release|x86 33 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|ARM.ActiveCfg = Release|ARM 34 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|ARM.Build.0 = Release|ARM 35 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|ARM.Deploy.0 = Release|ARM 36 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|x64.ActiveCfg = Release|x64 37 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|x64.Build.0 = Release|x64 38 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|x64.Deploy.0 = Release|x64 39 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|x86.ActiveCfg = Release|x86 40 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|x86.Build.0 = Release|x86 41 | {E390EC83-B1A0-4AD5-BCAB-81764D7BA538}.Release|x86.Deploy.0 = Release|x86 42 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|ARM.ActiveCfg = Debug|Any CPU 45 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|ARM.Build.0 = Debug|Any CPU 46 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x64.ActiveCfg = Debug|Any CPU 47 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x64.Build.0 = Debug|Any CPU 48 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x86.ActiveCfg = Debug|Any CPU 49 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Debug|x86.Build.0 = Debug|Any CPU 50 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|ARM.ActiveCfg = Release|Any CPU 53 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|ARM.Build.0 = Release|Any CPU 54 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x64.ActiveCfg = Release|Any CPU 55 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x64.Build.0 = Release|Any CPU 56 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x86.ActiveCfg = Release|Any CPU 57 | {E8C08C44-303E-4F2C-98CC-E22DBAC85C60}.Release|x86.Build.0 = Release|Any CPU 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel; 7 | using Windows.ApplicationModel.Activation; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | namespace ScriptDemo 19 | { 20 | /// 21 | /// Provides application-specific behavior to supplement the default Application class. 22 | /// 23 | sealed partial class App : Application 24 | { 25 | /// 26 | /// Initializes the singleton application object. This is the first line of authored code 27 | /// executed, and as such is the logical equivalent of main() or WinMain(). 28 | /// 29 | public App() 30 | { 31 | Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync( 32 | Microsoft.ApplicationInsights.WindowsCollectors.Metadata | 33 | Microsoft.ApplicationInsights.WindowsCollectors.Session); 34 | this.InitializeComponent(); 35 | this.Suspending += OnSuspending; 36 | } 37 | 38 | /// 39 | /// Invoked when the application is launched normally by the end user. Other entry points 40 | /// will be used such as when the application is launched to open a specific file. 41 | /// 42 | /// Details about the launch request and process. 43 | protected override void OnLaunched(LaunchActivatedEventArgs e) 44 | { 45 | 46 | #if DEBUG 47 | if (System.Diagnostics.Debugger.IsAttached) 48 | { 49 | this.DebugSettings.EnableFrameRateCounter = false; 50 | } 51 | #endif 52 | 53 | Frame rootFrame = Window.Current.Content as Frame; 54 | 55 | // Do not repeat app initialization when the Window already has content, 56 | // just ensure that the window is active 57 | if (rootFrame == null) 58 | { 59 | // Create a Frame to act as the navigation context and navigate to the first page 60 | rootFrame = new Frame(); 61 | 62 | rootFrame.NavigationFailed += OnNavigationFailed; 63 | 64 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 65 | { 66 | //TODO: Load state from previously suspended application 67 | } 68 | 69 | // Place the frame in the current Window 70 | Window.Current.Content = rootFrame; 71 | } 72 | 73 | if (rootFrame.Content == null) 74 | { 75 | // When the navigation stack isn't restored navigate to the first page, 76 | // configuring the new page by passing required information as a navigation 77 | // parameter 78 | rootFrame.Navigate(typeof(MainPage), e.Arguments); 79 | } 80 | // Ensure the current window is active 81 | Window.Current.Activate(); 82 | } 83 | 84 | /// 85 | /// Invoked when Navigation to a certain page fails 86 | /// 87 | /// The Frame which failed navigation 88 | /// Details about the navigation failure 89 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 90 | { 91 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 92 | } 93 | 94 | /// 95 | /// Invoked when application execution is being suspended. Application state is saved 96 | /// without knowing whether the application will be terminated or resumed with the contents 97 | /// of memory still intact. 98 | /// 99 | /// The source of the suspend request. 100 | /// Details about the suspend request. 101 | private void OnSuspending(object sender, SuspendingEventArgs e) 102 | { 103 | var deferral = e.SuspendingOperation.GetDeferral(); 104 | //TODO: Save application state and stop any background activity 105 | deferral.Complete(); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/ApplicationInsights.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/StoreLogo.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Templarian/Script/98314cb0bb2b88d70ea443591539dd71ceea2fef/ScriptDemo/ScriptDemo/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /ScriptDemo/ScriptDemo/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 |