public void if_elseif_else()
        {
            var token = new IfToken
            {
                Type = "if",
                Text = "Cast:\n\tif (\"%snapCast\" = \"OFF\") then\n\t{\n\t\twaitfor fully prepared\n\t\techo line 1\n\t} else if (\"something1\" = \"another\") then {\n\t\tpause 1\n\t\techo line 2\n\t} else {\n\t\tpause 7\n\t\techo line 3\n\t}\n\tput cast\n\tmatchre ManaCheck You strain\n\tmatchre ExpCheck snap\n\tmatchwait 4\n\tgoto ExpCheck\n\nExpCheck:\n\tpause 1",
                Blocks = new IfBlocks
                {
                    IfEval = "(\"%snapCast\" == \"OFF\")",
                    IfBlock = "{\n\t\tpause 0.3\n\t\techo line 1\n\t}",
                    ElseIf = "(\"something1\" == \"another\")",
                    ElseIfBlock = "{\n\t\tpause 0.2\n\t\techo line 2\n\t}",
                    ElseBlock = "{\n\t\tpause 0.1\n\t\techo snapcast %snapCast\n\t}"
                }
            };

            const string expected = "if (\"ON\" == \"OFF\")\nif result false\nif (\"something1\" == \"another\")\nif result false\npausing for 0.1 seconds\necho snapcast ON\n\n";

            theLocalVars.Set("snapCast", "ON");

            var task = theHandler.Execute(theScriptContext, token);

            Assert.True(task.IsCompleted);
            Assert.AreEqual(expected, theLog.Builder.ToString());
        }
        public void handles_single_equals()
        {
            var token = new IfToken
            {
                Type = "if",
                Text = "if (\"%snapcast\" = \"OFF\") then goto END",
                Blocks = new IfBlocks
                {
                    IfEval = "(\"%snapcast\" = \"OFF\")",
                    IfBlock = "goto END"
                }
            };

            const string expected = "if (\"OFF\" == \"OFF\")\nif result true\ngoto END\n";

            theLocalVars.Set("snapcast", "OFF");

            var task = theHandler.Execute(theScriptContext, token);

            Assert.True(task.IsCompleted);
            Assert.AreEqual(expected, theLog.Builder.ToString());
        }
        public void sets_linenumber()
        {
            var token = new IfToken
            {
                Type = "if",
                Text = "if (\"%snapcast\" = \"OFF\") then goto END",
                Blocks = new IfBlocks
                {
                    IfEval = "(\"%wait_mana\" = \"OFF\")",
                    IfEvalLineNumber = 10,
                    IfBlock = "{\n\t\twaitforre You begin\n\t}",
                    IfBlockLineNumber = 11
                }
            };

            const string expected = "if (\"OFF\" == \"OFF\")\nif result true\ngoto END\n";

            theLocalVars.Set("wait_mana", "ON");

            var task = theHandler.Execute(theScriptContext, token);

            Assert.True(task.IsCompleted);
            Assert.AreEqual(13, theScriptContext.LineNumber);
        }
        public void waits_for_match2()
        {
            var token = new IfToken
            {
                Type = "if",
                Text = "if (\"%snapcast\" == \"OFF\") then goto END\nelse goto elsewhere",
                Blocks = new IfBlocks
                {
                    IfEval = "(\"%snapcast\" == \"OFF\")",
                    IfBlock = "goto END",
                    ElseBlock = "goto elsewhere"
                }
            };

            theLocalVars.Set("snapcast", "ON");

            var task = theHandler.Execute(theScriptContext, token);

            Assert.True(task.IsCompleted);
            Assert.AreEqual("if (\"ON\" == \"OFF\")\nif result false\ngoto elsewhere\n", theLog.Builder.ToString());
            Assert.AreEqual("elsewhere", task.Result.Goto);
        }
        public void waits_for_match()
        {
            var token = new IfToken
            {
                Type = "if",
                Text = "if ($Outdoorsmanship.LearningRate >= %maxexp) then goto END",
                Blocks = new IfBlocks
                {
                    IfEval = "($Outdoorsmanship.LearningRate >= %maxexp)",
                    IfBlock = "goto END"
                }
            };

            theGameState.Set("Outdoorsmanship.LearningRate", "10");
            theLocalVars.Set("maxexp", "5");

            var task = theHandler.Execute(theScriptContext, token);

            Assert.True(task.IsCompleted);
            Assert.AreEqual("if (10 >= 5)\nif result true\ngoto END\n", theLog.Builder.ToString());
            Assert.AreEqual("END", task.Result.Goto);
        }
        public static TokenDefinitionRegistry Default()
        {
            var registry = new TokenDefinitionRegistry();

            registry.New(d => {
                d.Type = "exit";
                d.Pattern = "^exit";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = match.Value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "comment";
                d.Pattern = "^#.*";
                d.Ignore = true;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = match.Value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "label";
                d.Pattern = RegexPatterns.Label;
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = match.Groups[1].Value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "goto";
                d.Pattern = "^goto";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "waitfor";
                d.Pattern = "^waitfor\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "waitforre";
                d.Pattern = "^waitforre\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "match";
                d.Pattern = "^match\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    const string Goto_Regex = "^match\\b\\s([\\w\\.-]+)\\s(.*)";
                    var gotoMatch = Regex.Match(source, Goto_Regex, RegexOptions.IgnoreCase);
                    var token = new MatchToken
                    {
                        Text = source,
                        Type = def.Type,
                        IsRegex = false,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim(),
                        Goto = gotoMatch.Groups[1].Value,
                        Pattern = gotoMatch.Groups[2].Value.Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "matchre";
                d.Pattern = "^matchre\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    const string Goto_Regex = "^matchre\\b\\s([\\w\\.-]+)\\s(.*)";
                    var gotoMatch = Regex.Match(source, Goto_Regex, RegexOptions.IgnoreCase);
                    var token = new MatchToken
                    {
                        Text = source,
                        Type = def.Type,
                        IsRegex = true,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim(),
                        Goto = gotoMatch.Groups[1].Value,
                        Pattern = gotoMatch.Groups[2].Value.Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "matchwait";
                d.Pattern = "^matchwait";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "pause";
                d.Pattern = "^pause";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "put";
                d.Pattern = "^put";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "echo";
                d.Pattern = "^echo";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    if(token.Value == null || token.Value.Length == 0 || !token.Value.EndsWith("\n")) {
                        token.Value += "\n";
                    }
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "var";
                d.Pattern = "^var";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "var";
                d.Pattern = "^setvariable";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "unvar";
                d.Pattern = "^unvar\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "hasvar";
                d.Pattern = "^hasvar\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "save";
                d.Pattern = "^save";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {
                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "if";
                d.Pattern = "^if\\b";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new IfToken
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "if_";
                d.Pattern = "^if_(\\d+)";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new IfToken
                    {
                        Text = source,
                        Type = def.Type,
                        Value = match.Value,
                        ReplaceBlocks = false,
                        Blocks = new IfBlocks
                        {
                            IfEval = match.Groups[1].Value,
                            IfBlock = value
                        }
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "move";
                d.Pattern = "^move";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "nextroom";
                d.Pattern = "^nextroom";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "action";
                d.Pattern = "^action\\b(.*)\\bwhen\\b(.*)";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new ActionToken
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value,
                        Action = match.Groups[1].Value.Trim(),
                        When = match.Groups[2].Value.Trim()
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "send";
                d.Pattern = "^send";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "debuglevel";
                d.Pattern = "^debuglevel";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "parse";
                d.Pattern = "^parse";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "containsre";
                d.Pattern = "^containsre";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "gosub";
                d.Pattern = "^gosub";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var value = source.Substring(match.Index + match.Length, source.Length - (match.Index + match.Length)).Trim();
                    var labelMatch = Regex.Match(value, RegexPatterns.Gosub);
                    var splitArgs = Regex
                        .Matches(value, RegexPatterns.Arguments)
                        .Cast<Match>()
                        .Select(m => m.Groups["match"].Value.Trim('"'))
                        .Skip(1)
                        .ToArray();

                    var token = new GotoToken
                    {
                        Text = source,
                        Type = def.Type,
                        Value = value,
                        Label = labelMatch.Groups["label"].Value,
                        Args = splitArgs
                    };
                    return token;
                };
            });

            registry.New(d => {
                d.Type = "return";
                d.Pattern = "^return";
                d.Ignore = false;
                d.BuildToken = (source, match, def)=> {

                    var token = new Token
                    {
                        Text = source,
                        Type = def.Type,
                        Value = "return"
                    };
                    return token;
                };
            });

            return registry;
        }