private MatchResult CheckExpressionMatches(CompilerPlugin plugin, List <TokenMatch> matches, Dictionary <string, object> args, int peekCount, int matchCount)
        {
            var isMatch      = true;
            var token        = peekCount == 0 ? this.TokenIt.NextToken : this.TokenIt.Peek(peekCount);
            var totalMatched = matchCount;

            foreach (var match in matches)
            {
                var continueCheck  = false;
                var trackNamedArgs = true;
                var valueMatched   = false;

                // Termninators
                if (match.TokenType == "@exprTerminators" &&
                    (Terminators.ExpFlexibleEnd.ContainsKey(token.Token) || Terminators.ExpThenEnd.ContainsKey(token.Token))
                    )
                {
                    // Don't increment the peekcount
                    isMatch = totalMatched >= plugin.TotalRequiredMatches;
                    break;
                }
                // Check for ";" and EOF ( end of file/text )
                if (token.Token == Tokens.Semicolon || token.Token == Tokens.EndToken)
                {
                    isMatch = totalMatched >= plugin.TotalRequiredMatches;
                    break;
                }

                // Check 1: Group tokens ?
                if (match.IsGroup)
                {
                    var submatches = ((TokenGroup)match).Matches;
                    var result     = CheckExpressionMatches(plugin, submatches, args, peekCount, totalMatched);
                    if (match.IsRequired && !result.Success)
                    {
                        isMatch = false;
                        break;
                    }
                    if (result.Success)
                    {
                        peekCount = result.TokenCount;
                        if (match.IsRequired)
                        {
                            totalMatched += result.TotalMatched;
                        }
                    }
                }
                // Check 2: starttoken?
                else if (match.TokenType == "@starttoken")
                {
                    continueCheck = true;
                    totalMatched++;
                }
                // Check 2a: tokenmap1
                else if (match.TokenType == "@tokenmap1")
                {
                    if (plugin.TokenMap1 == null || !plugin.TokenMap1.ContainsKey(token.Token.Text))
                    {
                        isMatch = false;
                        break;
                    }
                    continueCheck = true;
                    totalMatched++;
                }
                else if (match.TokenType == "@tokenmap2")
                {
                    if (plugin.TokenMap2 == null || !plugin.TokenMap2.ContainsKey(token.Token.Text))
                    {
                        isMatch = false;
                        break;
                    }
                    continueCheck = true;
                    totalMatched++;
                }
                // Check 2c: "identSymbol" must exist
                else if (match.TokenType == "@identsymbol")
                {
                    var symbolExists = this.Symbols.Contains(token.Token.Text);
                    continueCheck = symbolExists;
                    if (!continueCheck)
                    {
                        isMatch = false;
                        break;
                    }
                    totalMatched++;
                }
                // Check 2c: "identSymbol" must exist
                else if (match.TokenType == "@singularsymbol")
                {
                    var plural       = token.Token.Text + "s";
                    var symbolExists = this.Symbols.Contains(plural);
                    continueCheck = symbolExists;
                    if (!continueCheck)
                    {
                        isMatch = false;
                        break;
                    }
                    totalMatched++;
                }
                // Check 2d: paramlist = @word ( , @word )* parameter names
                else if (match.TokenType == "@paramnames")
                {
                    var isvalidParamList = true;
                    var maxParams        = 10;
                    var totalParams      = 0;
                    var paramList        = new List <object>();

                    while (totalParams <= maxParams)
                    {
                        var token2 = this.TokenIt.Peek(peekCount, false);
                        if (token2.Token == Tokens.Comma)
                        {
                            peekCount++;
                        }
                        else if (token2.Token.Kind == TokenKind.Ident)
                        {
                            paramList.Add(token2.Token.Text);
                            peekCount++;
                        }
                        else
                        {
                            peekCount--;
                            break;
                        }
                        totalParams++;
                    }
                    isMatch       = isvalidParamList;
                    continueCheck = isMatch;
                    if (continueCheck)
                    {
                        trackNamedArgs = false;
                        if (!string.IsNullOrEmpty(match.Name))
                        {
                            args[match.Name]           = token;
                            args[match.Name + "Value"] = new LArray(paramList);
                        }
                        totalMatched++;
                    }
                    else
                    {
                        break;
                    }
                }
                // Check 3a: Optional words with text
                else if (!match.IsRequired && match.Text != null && match.Text != token.Token.Text)
                {
                    continueCheck = false;
                }
                // Check 3b: Optional words matched
                else if (!match.IsRequired && match.IsMatchingValue(token.Token))
                {
                    continueCheck = true;
                }
                // Check 4: Optional word not matched
                else if (!match.IsRequired && !match.IsMatchingValue(token.Token))
                {
                    continueCheck = false;
                }
                // Check 5a: Expected word
                else if (match.IsRequired && match.TokenType == null && match.Text == token.Token.Text)
                {
                    continueCheck = true;
                    totalMatched++;
                }
                // Check 5b: Expected word in list
                else if (match.IsRequired && match.TokenType == null && match.Values != null)
                {
                    if (!match.IsMatchingValue(token.Token))
                    {
                        isMatch = false;
                        break;
                    }
                    continueCheck = true;
                    valueMatched  = true;
                    totalMatched++;
                }
                // Check 6: check the type of n1
                else if (match.IsMatchingType(token.Token))
                {
                    continueCheck = true;
                    totalMatched++;
                }
                else
                {
                    isMatch = false;
                    break;
                }
                if (continueCheck)
                {
                    if (!string.IsNullOrEmpty(match.Name) && trackNamedArgs)
                    {
                        args[match.Name] = token;
                        if (match.TokenPropEnabled)
                        {
                            // 1. figure out which token map to use.
                            var lookupmap = plugin.StartTokenMap;

                            if (match.TokenType == "@tokenmap1")
                            {
                                lookupmap = plugin.TokenMap1;
                            }
                            else if (match.TokenType == "@tokenmap2")
                            {
                                lookupmap = plugin.TokenMap2;
                            }

                            // Case 1: Start token replacement value
                            if (match.TokenPropValue == "value")
                            {
                                var startToken = token.Token.Text;
                                args[match.Name + "Value"] = lookupmap[startToken];
                            }
                            // Case 2: Token value
                            else if (match.TokenPropValue == "tvalue")
                            {
                                LObject val = LObjects.Null;
                                if (match.TokenType == "@number")
                                {
                                    val = new LNumber((double)token.Token.Value);
                                }
                                else if (match.TokenType == "@time")
                                {
                                    val = new LTime((TimeSpan)token.Token.Value);
                                }
                                else if (match.TokenType == "@word")
                                {
                                    val = new LString((string)token.Token.Value);
                                }
                                else if (match.TokenType == "@starttoken")
                                {
                                    val = new LString(token.Token.Text);
                                }
                                args[match.Name + "Value"] = val;
                            }
                            // Case 2: Token value
                            else if (match.TokenPropValue == "tvaluestring")
                            {
                                LObject val = LObjects.Null;
                                if (match.TokenType == "@number")
                                {
                                    val = new LString(((double)token.Token.Value).ToString(CultureInfo.InvariantCulture));
                                }
                                else if (match.TokenType == "@time")
                                {
                                    val = new LString(((TimeSpan)token.Token.Value).ToString());
                                }
                                else if (match.TokenType == "@starttoken")
                                {
                                    val = new LString(token.Token.Text);
                                }
                                else if (match.TokenType == "@word")
                                {
                                    val = new LString(token.Token.Text);
                                }
                                else if (match.TokenType == "@singularsymbol")
                                {
                                    val = new LString(token.Token.Text);
                                }
                                args[match.Name + "Value"] = val;
                            }
                        }
                        // matching values
                        else if (valueMatched)
                        {
                            args[match.Name + "Value"] = token.Token.Text;
                        }
                    }
                    // Matched: increment.
                    peekCount++;
                    token = this.TokenIt.Peek(peekCount, false);
                }
            }
            var res = new MatchResult(isMatch, null, args);

            res.TotalMatched = totalMatched;
            res.TokenCount   = peekCount;
            return(res);
        }
Beispiel #2
0
        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("$DateToken"))
                    plugins = _pluginTokens["$DateToken"];
            }
            if (plugins == null)
                return false;

            _matchTokenResult = new MatchResult(false, null, null);
            foreach (var plugin in plugins)
            {
                if (string.IsNullOrEmpty(plugin.Grammar))
                {
                    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 = IsGrammarMatch(plugin);
                    if(result.Success)
                    {
                        _matchTokenResult = result;
                        break;
                    }
                }
            }
            return _matchTokenResult.Success;
        }
Beispiel #3
0
        private MatchResult CheckMatches(CompilerPlugin plugin, List<TokenMatch> matches, Dictionary<string, object> args, int peekCount)
        {
            var isMatch = true;
            var token = peekCount == 0 ? this.TokenIt.NextToken : this.TokenIt.Peek(peekCount);
            foreach (var match in matches)
            {
                var incrementPeek = false;

                // Check 1: Group tokens ?
                if(match.IsGroup)
                {
                    var submatches = ((TokenGroup) match).Matches;
                    var result = CheckMatches(plugin, submatches, args, peekCount);
                    if(match.IsRequired && !result.Success)
                    {
                        isMatch = false;
                        break;
                    }
                }
                // Check 2: starttoken?
                else if (match.TokenType == "@starttoken")
                {
                    incrementPeek = true;
                }
                // Check 3a: Optional words with text
                else if (!match.IsRequired && match.Text != null && match.Text != token.Token.Text)
                {
                    incrementPeek = false;
                }
                // Check 3b: Optional words matched
                else if (!match.IsRequired && match.IsMatchingValue(token.Token))
                {
                    incrementPeek = true;
                }
                // Check 4: Optional word not matched
                else if (!match.IsRequired && !match.IsMatchingValue(token.Token))
                {
                    incrementPeek = false;
                }
                // Check 5: Expected word
                else if (match.IsRequired && match.TokenType == null && match.Text == token.Token.Text)
                {
                    incrementPeek = true;
                }
                // Check 6: check the type of n1
                else if (match.IsMatchingType(token.Token))
                {
                    incrementPeek = true;
                }
                else
                {
                    isMatch = false;
                    break;
                }
                if (incrementPeek)
                {
                    if (!string.IsNullOrEmpty(match.Name))
                    {
                        args[match.Name] = token;
                        if(match.TokenPropEnabled && match.TokenPropValue == "value")
                        {
                            var startToken = token.Token.Text;
                            args[match.Name + "-value"] = plugin.StartTokenMap[startToken];
                        }
                    }
                    // Matched: increment.
                    peekCount++;
                    token = this.TokenIt.Peek(peekCount);
                }
            }
            var res = new MatchResult(isMatch, null, args);
            res.TokenCount = peekCount;
            return res;
        }
Beispiel #4
0
        /// <summary>
        /// Whether or not there is a compiler plugin that can handle the token provided.
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool CanHandleExp(Token token)
        {
            // Avoid literal strings
            if (token.Kind == TokenKind.LiteralString)
                return false;

            // Start token exists to trigger plugin check?
            if (!_pluginExprs.ContainsKey(token.Text))
                return false;

            _matchResult = EmtpyMatch;
            _matchResult = IsMatch();
            return _matchResult.Success;
        }
Beispiel #5
0
        /// <summary>
        /// Whether or not there is a plugin that matches the current tokens.
        /// </summary>
        /// <returns></returns>
        public MatchResult IsMatch()
        {
            var token = this.TokenIt.NextToken;

            // 1. no start token?
            if (!this._pluginExprs.ContainsKey(token.Token.Text))
                return this.EmtpyMatch;

            // 2. Get matching plugin.
            var plugins = this._pluginExprs[token.Token.Text];

            // 3. Check for matching plugin.
            var result = this.EmtpyMatch;
            foreach (var plugin in plugins)
            {
                // 4. auto match plugin?
                if (plugin.IsAutoMatched)
                {
                    result = new MatchResult(true, plugin, null);
                    return result;
                }

                // 5. Check Grammer.
                result = IsGrammarMatch(plugin);
                if (result.Success)
                {
                    break;
                }
            }
            return result;
        }