/// <summary>
        /// Register the compiler plugin.
        /// </summary>
        /// <param name="plugin"></param>
        public void Register(CompilerPlugin plugin)
        {
            _allPlugins.Add(plugin);
            if (!plugin.IsEnabled)
            {
                return;
            }

            if (plugin.PluginType == "expr" && plugin.StartTokens.Length > 0)
            {
                foreach (var startToken in plugin.StartTokens)
                {
                    var tokenPlugins = _pluginExprs.ContainsKey(startToken)
                                           ? _pluginExprs[startToken]
                                           : new List <CompilerPlugin>();
                    tokenPlugins.Add(plugin);
                    _pluginExprs[startToken] = tokenPlugins;
                }
            }
            else if (plugin.PluginType == "lexer" && plugin.StartTokens.Length > 0)
            {
                var list = new List <CompilerPlugin>();
                list.Add(plugin);
                foreach (var startToken in plugin.StartTokens)
                {
                    _pluginLexTokens[startToken] = list;
                }
            }
            else if (plugin.PluginType == "token")
            {
                var tplugin = new TokenReplacePlugin();

                var hasStartTokens = plugin.StartTokens != null && plugin.StartTokens.Length > 0;
                var list           = new List <CompilerPlugin>();
                plugin.Handler = tplugin;
                list.Add(plugin);

                if (hasStartTokens)
                {
                    foreach (var startToken in plugin.StartTokens)
                    {
                        _pluginTokens[startToken] = list;
                    }
                }
                if (plugin.TokenReplacements != null && plugin.TokenReplacements.Count > 0)
                {
                    foreach (var replacements in plugin.TokenReplacements)
                    {
                        var alias       = replacements[0];
                        var replaceWith = replacements[1];
                        tplugin.SetupReplacement(alias, replaceWith);
                        if (!hasStartTokens)
                        {
                            _pluginTokens[alias] = list;
                        }
                    }
                }
            }
        }
        public bool CanHandleTok(Token token, bool isCurrent)
        {
            List <CompilerPlugin> plugins = null;

            // Case 1: Can not overtake identifiers that are actually variables(symbols) in current scope.
            if (token.Kind == TokenKind.Ident && this.Symbols != null && this.Symbols.Contains(token.Text))
            {
                return(false);
            }

            // Case 2: Ident - specific word
            if (token.Kind == TokenKind.Ident && _pluginTokens.ContainsKey(token.Text))
            {
                plugins = _pluginTokens[token.Text];
            }
            // Case 3: General symbol e.g. $Ident $DateToken $Time
            else if (token.Kind == TokenKind.LiteralDate)
            {
                if (_pluginTokens.ContainsKey(_typeDateToken))
                {
                    plugins = _pluginTokens[_typeDateToken];
                }
            }
            if (plugins == null)
            {
                return(false);
            }

            _matchTokenResult = new MatchResult(false, null, null);
            foreach (var plugin in plugins)
            {
                if (string.IsNullOrEmpty(plugin.GrammarMatch))
                {
                    var tokenPlugin = plugin.Handler as TokenReplacePlugin;
                    tokenPlugin.TokenIt = this.TokenIt;
                    if (tokenPlugin.CanHandle(token, isCurrent))
                    {
                        _matchTokenResult           = new MatchResult(true, plugin, null);
                        this.LastMatchedTokenPlugin = tokenPlugin;
                        break;
                    }
                }
                else
                {
                    var result = IsGrammarMatchOnExpression(plugin);
                    if (result.Success)
                    {
                        _matchTokenResult = result;
                        break;
                    }
                }
            }
            return(_matchTokenResult.Success);
        }