Exemple #1
0
            /// <inheritdoc />
            public string EvaluateExpression(string expression)
            {
                string[]      exprParts = expression.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                StringBuilder sb        = new StringBuilder(1024);

                for (int i = -1, ilen = exprParts.Length; ++i != ilen;)
                {
                    string            exprPart         = exprParts[i];
                    IPatternParameter patternParameter = _sequence[i];
                    string            result           = patternParameter.EvaluateExpression(exprPart);
                    sb.Append($"{result}, ");
                }

                return(sb.Length == 0
                        ? string.Empty
                        : sb.ToString(0, sb.Length - 2)
                       );
            }
Exemple #2
0
        /// <summary>
        /// Returns an instance of <see cref="IPatternParameter"/> that combines the given
        /// pattern parameter instances.
        /// </summary>
        private static IPatternParameter Combine(IPatternParameter pp1, IPatternParameter pp2)
        {
            if (pp1 == null)
            {
                return(pp2);
            }
            if (pp2 == null)
            {
                return(pp1);
            }

            if (pp1 is CombinedPatternParameter cpp1)
            {
                cpp1.Add(pp2);
            }
            else if (pp2 is CombinedPatternParameter cpp2)
            {
                cpp2.Add(pp1);
            }

            return(new CombinedPatternParameter(pp1, pp2));
        }
        /// <summary>
        /// Evaluates the given <paramref name="instruction"/> using the given <paramref name="instructionInfo"/>. Any resolved parameter is added
        /// to <paramref name="paramCache"/>.
        /// </summary>
        /// <param name="instruction">Directive to evaluate</param>
        /// <param name="instructionInfo">Instruction that provides the meta data</param>
        /// <param name="paramCache">Parameter cache</param>
        /// <returns>Evaluation result</returns>
        public IInstructionEvaluationResult Evaluate(string instruction, InstructionTranslationInfo instructionInfo, IDictionary <string, IPatternParameter> paramCache)
        {
            if (string.IsNullOrEmpty(instruction))
            {
                throw new ArgumentNullException(nameof(instruction));
            }
            if (instructionInfo == null)
            {
                throw new ArgumentNullException(nameof(instructionInfo));
            }

            string wordSequence = instruction;

            // Remove dot
            if (wordSequence.EndsWith("."))
            {
                wordSequence = wordSequence.Substring(0, wordSequence.Length - 1);
            }

            // Value sequence recognition
            string valueSequenceString = null;

            wordSequence = Regex.Replace(wordSequence,
                                         @"(?<top>""[^""]+"")(?<nav>\s(?<child>""[^""]+""))*\s(?<value>""[^""]+"")",
                                         match => {
                string prime    = match.Groups["top"].Value;
                string sslValue = string.Join(", ", match.Groups["child"].Captures.ToArray());
                string value    = match.Groups["value"].Value;

                string[] joinSet    = string.IsNullOrEmpty(sslValue) ? new[] { prime, value } : new[] { prime, sslValue, value };
                valueSequenceString = string.Join(", ", joinSet);

                return(ValueSequenceToken);
            });

            // Split to words
            string[] words = wordSequence.SplitToBuddyTokens();
            if (words.Length == 0)
            {
                return(EvaluationResult.Error(wordSequence, instructionInfo.Instruction, "Instruction is empty after split"));
            }

            words = words.StripSpecialCharacters();
            if (words.Length == 0)
            {
                return(EvaluationResult.Error(wordSequence, instructionInfo.Instruction, "Instruction is empty after strip"));
            }

            // Normalize variants
            if (instructionInfo.Instruction is IVariantInstruction variantInstruction)
            {
                words = variantInstruction.Normalize(words);
            }

            // Iterate words and check for match
            int wordIndex = 0;

            for (IEnumerator <IInstructionPatternToken> tokenItr = instructionInfo.GetInstructionPatternTokenEnumerator(); tokenItr.MoveNext();)
            {
                IInstructionPatternToken token = tokenItr.Current;
                if (token == null)
                {
                    throw new InvalidOperationException("Token iterator provided NULL token");
                }

                string word;

                // Take the word from the sequence
                if (wordIndex < words.Length)
                {
                    word = words[wordIndex];
                }
                else     // We have more tokens than words
                // All remaining tokens must be not mandatory or we have an error
                // So they must handle an unset value
                {
                    word = PatternParameter.Unset;
                }

                // If we have a match, everything is fine
                if (token.DoesMatch(word))
                {
                    wordIndex++;

                    // Resolve parametrized tokens
                    if (token is IParametrizedInstructionPatternToken parametrizedToken)
                    {
                        IPatternParameter patternParameter = parametrizedToken.Value;
                        string            parameterName    = patternParameter.Name;

                        // If the value has been replaced by a ValueSequenceToken before, we have to re-replace it now
                        if (valueSequenceString != null)                                 // Something must have been replaced
                        {
                            if (patternParameter.Value.Value.Equals(ValueSequenceToken)) // Is this the correct parameter?
                            {
                                ((AbstractPatternParameter)patternParameter).SetValue(valueSequenceString);
                            }
                        }


                        // Add value to cache
                        paramCache.Add(parameterName, patternParameter);
                    }

                    continue;
                }

                // If the token is not mandatory, we can go forward
                if (!token.IsMandatory)
                {
                    continue;
                }

                return(EvaluationResult.Error(
                           wordSequence,
                           instructionInfo.Instruction,
                           $"{FormatWordIndex(wordIndex)} word of instruction " +
                           $"does not match expected token '{token.ToHumanReadableString()}'. " +
                           $"Word is '{word}'"
                           ));
            }

            return(EvaluationResult.Ok);
        }
Exemple #4
0
        /// <summary>
        /// Creates a string representing a directive based on the given <paramref name="actionStep"/> and the
        /// given <paramref name="parameters"/>.
        /// </summary>
        /// <param name="actionStep">Action step to format</param>
        /// <param name="parameters">Parameters to use</param>
        /// <returns>String representing a directive based on the given action step</returns>
        /// <exception cref="ArgumentNullException">If any parameter is NULL</exception>
        /// <exception cref="InstructionFormattingException">If not all declared parameters could be replaced</exception>
        public virtual string ToString(IBuddyTranslationInstruction actionStep, IDictionary <string, IPatternParameter> parameters)
        {
            if (actionStep == null)
            {
                throw new ArgumentNullException(nameof(actionStep));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            string tdilPattern = actionStep.TdilPattern;
            string result      = tdilPattern;

            if (actionStep is IReferableInstruction referableInstruction)
            {
                string resultReference = referableInstruction.ResultReferencePattern;
                resultReference = resultReference.Replace("#", "1");
                result          = $"{resultReference} = {result}";
            }

            // Process all parameter references
            MatchCollection matches = _tdilPatternParameterRegex.Matches(result);

            for (IEnumerator matchItr = matches.GetEnumerator(); matchItr.MoveNext();)
            {
                Match match = (Match)matchItr.Current;
                if (match == null)
                {
                    continue;
                }

                Group paramRefGrp = match.Groups["paramRef"];
                Group closureGrp  = match.Groups["closure"];
                Group nameGrp     = match.Groups["name"];

                EClosureType closureType         = EClosureType.None;
                string       parameterExpression = paramRefGrp.Value;
                string[]     pureParamNames;

                // Do we have a closure with alternatives?
                if (closureGrp.Success)
                {
                    string coreFunction = parameterExpression.Substring(2, parameterExpression.Length - 3);
                    if (coreFunction.IndexOf('|') != -1)
                    {
                        closureType    = EClosureType.Alternative;
                        pureParamNames = coreFunction.Split('|');
                    }
                    else
                    {
                        closureType    = EClosureType.Conjunction;
                        pureParamNames = coreFunction.Split('&');
                    }
                }
                else     // Plain old reference
                {
                    pureParamNames = new[] { nameGrp.Value };
                }

                // Look up referenced pattern parameter
                string            parameterValueFunction = null;
                IPatternParameter patternParameter       = null;
                for (int i = -1; ++i != pureParamNames.Length;)
                {
                    string pureParamName    = pureParamNames[i];
                    string reducedParamName = pureParamName.Split('.')[0];
                    if (parameters.TryGetValue(reducedParamName, out var locPatternParameter))
                    {
                        string assignedValueFunction = $"${pureParamName}";

                        // When this is a conjunction, we have to combine all pattern parameter
                        if (closureType == EClosureType.Conjunction)
                        {
                            parameterValueFunction = string.Concat(parameterValueFunction ?? string.Empty, ",", assignedValueFunction);
                            patternParameter       = Combine(patternParameter, locPatternParameter);
                            continue;
                        }

                        // In all other cases, just resolve the first matching pattern parameter
                        patternParameter       = locPatternParameter;
                        parameterValueFunction = assignedValueFunction;
                        break;
                    }
                }

                // Do we have one?
                if (patternParameter == null)
                {
                    throw new InstructionFormattingException($"The TDIL pattern '{tdilPattern}' contains a mandatory parameter '{parameterExpression}' that could not be resolved!");
                }

                // Calculate value
                string valueStr = patternParameter.EvaluateExpression(parameterValueFunction);
                if (valueStr == null)
                {
                    throw new InstructionFormattingException($"Expression '{parameterExpression}' could not be evaluated by pattern parameter of '{patternParameter}'");
                }

                // Insert and replace
                result = result.Replace(parameterExpression, valueStr);
            }

            // Ensure all parameters have been replaced
            if (result.Contains('~'))
            {
                throw new InstructionFormattingException($"At least one parameter could not be set. Pattern is '{tdilPattern}'. Result is '{result}'.");
            }

            return(result);
        }
Exemple #5
0
 /// <summary> Adds the given instance to the sequence. </summary>
 public void Add(IPatternParameter pp)
 {
     _sequence.Add(pp);
 }
Exemple #6
0
 /// <summary> Creates a new instance by combining the given instances. </summary>
 public CombinedPatternParameter(IPatternParameter pp1, IPatternParameter pp2)
 {
     _sequence.Add(pp1);
     _sequence.Add(pp2);
 }