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); }
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; }
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; }
public MatchResult IsMatch(List<CompilerPlugin> plugins) { // 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 = IsGrammarMatchOnExpression(plugin); if (result.Success) { break; } } return result; }
/// <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; List<CompilerPlugin> plugins = null; // Start token exists to trigger plugin check? if (_pluginExprs.ContainsKey(token.Text)) { plugins = _pluginExprs[token.Text]; } else if (token.Kind == TokenKind.LiteralNumber) { if (_pluginExprs.ContainsKey(_typeNumberToken)) plugins = _pluginExprs[_typeNumberToken]; } else if (token.Kind == TokenKind.Ident) { if (_pluginExprs.ContainsKey(_typeIdentSymbolToken)) { if (this.Symbols.Contains(token.Text)) { plugins = _pluginExprs[_typeIdentSymbolToken]; } } } if (plugins == null) return false; _matchResult = EmtpyMatch; _matchResult = IsMatch(plugins); return _matchResult.Success; }