Пример #1
0
        protected string defineVariable(PreparedData prepared, string evaluated)
        {
            evaluated = vSignOperation(prepared, evaluated);

            Log.Debug("Evaluate: ready to define variable - '{0}':'{1}'",
                      prepared.variable.name,
                      prepared.variable.project);

            uvariable.set(prepared.variable.name, prepared.variable.project, evaluated);
            uvariable.evaluate(prepared.variable.name, prepared.variable.project, new EvaluatorBlank(), true);

            tSignOperation(prepared, ref evaluated);
            return(String.Empty);
        }
Пример #2
0
        /// <summary>
        /// The final value from prepared information
        /// </summary>
        /// <param name="prepared"></param>
        protected string evaluate(PreparedData prepared)
        {
            string evaluated = String.Empty;

            string custom = customRule(prepared.property.unevaluated, prepared.property.project);

            if (custom != null)
            {
                Log.Trace("Evaluate: custom '{0}'", custom);
                evaluated = evaluate(custom, null);
            }
            else if (prepared.variable.type == PreparedData.ValueType.StringFromDouble ||
                     prepared.variable.type == PreparedData.ValueType.StringFromSingle ||
                     !String.IsNullOrEmpty(prepared.variable.name))
            {
                //Note: * content from double quotes should be already evaluated in prev. steps.
                //      * content from single quotes shouldn't be evaluated by rules with protector above.
                Log.Trace("Evaluate: use content from string or use escaped property");
                evaluated = prepared.property.unevaluated;
            }
            else if (!prepared.property.complex)
            {
                Log.Trace("Evaluate: use getProperty");
                evaluated = getProperty(prepared.property.unevaluated, prepared.property.project);
                try {
                    evaluated = unlooping(evaluated, prepared, false);
                }
                catch (PossibleLoopException) {
                    // last chance with direct evaluation
                    evaluated = evaluate(prepared.property.unevaluated, prepared.property.project);
                    evaluated = unlooping(evaluated, prepared, true);
                }
            }
            else
            {
                Log.Trace("Evaluate: use evaluation with msbuild engine");
                evaluated = evaluate(prepared.property.unevaluated, prepared.property.project);
                evaluated = unlooping(evaluated, prepared, true);
            }
            Log.Debug("Evaluated: '{0}'", evaluated);

            // updating of variables

            if (!String.IsNullOrEmpty(prepared.variable.name))
            {
                evaluated = defineVariable(prepared, evaluated);
            }

            return(evaluated);
        }
Пример #3
0
        protected void tSignOperation(PreparedData prepared, ref string evaluated)
        {
#if DEBUG
            Log.Trace($"tSignOperation: '{prepared.variable.tSign}'");
#endif

            if (prepared.variable.tSign == PreparedData.TSignType.DefProperty)
            {
                defProperty(prepared.variable, evaluated);
            }
            else if (prepared.variable.tSign == PreparedData.TSignType.UndefProperty)
            {
                undefProperty(prepared.variable);
            }
        }
Пример #4
0
        protected string vSignOperation(PreparedData prepared, string val)
        {
            if (prepared.variable.vSign == PreparedData.VSignType.Default)
            {
                return(val);
            }

            var  left     = uvariable.get(prepared.variable.name, prepared.variable.project) ?? "0";
            bool isNumber = RPattern.IsNumber.IsMatch(left);

            Log.Trace($"vSignOperation: '{prepared.variable.vSign}'; `{left}` (isNumber: {isNumber})");

            if (prepared.variable.vSign == PreparedData.VSignType.Increment)
            {
                if (!isNumber)
                {
                    // equiv.: $(var = $([System.String]::Concat($(var), "str")) )
                    return(left + val);
                }

                // $(var = $([MSBuild]::Add($(var), 1)) )
                // TODO: additional check for errors from right string $(i += 'test') ... this correct: $(i += $(i))
                return(evaluate($"$([MSBuild]::Add('{left}', '{val}'))", prepared.variable.project));
            }

            if (prepared.variable.vSign == PreparedData.VSignType.Decrement)
            {
                if (!isNumber)
                {
                    throw new InvalidArgumentException($"Argument `{val}` is not valid for operation '-=' or it is not supported yet.");
                }

                // $(var = $([MSBuild]::Subtract($(var), 1)) )
                return(evaluate($"$([MSBuild]::Subtract('{left}', '{val}'))", prepared.variable.project));
            }

            return(val);
        }
Пример #5
0
        /// <summary>
        /// Prepare data for next evaluation step.
        /// </summary>
        /// <param name="raw">a single container e.g.: '(..data..)'</param>
        /// <exception cref="IncorrectSyntaxException"></exception>
        protected PreparedData prepare(string raw)
        {
            Match m = Regex.Match(raw.Trim(), String.Format(@"^\(
                                                                  (?:
                                                                    \s*
                                                                    ([A-Za-z_0-9]+) # 1 -> variable name (optional)
                                                                    \s*=\s*
                                                                    (?: {0}         # 2 -> string data inside double quotes
                                                                        |
                                                                        {1}         # 3 -> string data inside single quotes
                                                                    )?
                                                                  )?
                                                                  (?:
                                                                     (.+)           # 4 -> unevaluated data
                                                                     (?<!:):
                                                                     ([^:)]+)       # 5 -> specific project for variable if 1 is present or for unevaluated data
                                                                   |                # or:
                                                                     (.+)           # 6 -> unevaluated data
                                                                  )?
                                                              \)$",
                                                                  RPattern.DoubleQuotesContent,
                                                                  RPattern.SingleQuotesContent
                                                            ),
                                                            RegexOptions.IgnorePatternWhitespace);

            if(!m.Success) {
                throw new IncorrectSyntaxException("prepare: failed - '{0}'", raw);
            }

            Group rVariable         = m.Groups[1];
            Group rStringDataD      = m.Groups[2];
            Group rStringDataS      = m.Groups[3];
            Group rDataWithProject  = m.Groups[4];
            Group rProject          = m.Groups[5];
            Group rData             = m.Groups[6];

            PreparedData ret = new PreparedData()
            {
                property = new PreparedData.Property() {
                    raw = raw
                }
            };
            //Log.Trace("prepare: raw '{0}'", raw);

            /* Variable */

            if(rVariable.Success) {
                ret.variable.name = rVariable.Value;
                // all $() in right operand cannot be evaluated because it's escaped and already unwrapped property.
                // i.e. this already should be evaluated with prev. steps - because we are moving upward from deepest container !
                Log.Trace("prepare: variable name = '{0}'", ret.variable.name);
            }

            /* Data */

            if(rStringDataD.Success) {
                ret.property.unevaluated    = rStringDataD.Value.Replace("\\\"", "\""); //TODO:
                ret.variable.type           = PreparedData.ValueType.StringFromDouble;
            }
            else if(rStringDataS.Success) {
                ret.property.unevaluated    = rStringDataS.Value.Replace("\\'", "'"); //TODO:
                ret.variable.type           = PreparedData.ValueType.StringFromSingle;
            }
            else {
                ret.property.unevaluated    = ((rDataWithProject.Success)? rDataWithProject : rData).Value.Trim();
                ret.variable.type           = (rVariable.Success)? PreparedData.ValueType.Unknown : PreparedData.ValueType.Property;
            }

            ret.property.complex = !isPropertySimple(ref ret.property.unevaluated);

            Log.Trace("prepare: value = '{0}'({1})", ret.property.unevaluated, ret.variable.type);
            Log.Trace("prepare: complex {0}", ret.property.complex);

            /* Project */

            if(rDataWithProject.Success)
            {
                string project = rProject.Value.Trim();

                if(rVariable.Success) {
                    //TODO: non standard! but it also can be as a $(varname = $($(..data..):project))
                    ret.variable.project = project;
                }
                else {
                    ret.property.project = project;
                }
            }

            Log.Trace("prepare: project [v:'{0}'; p:'{1}']", ret.variable.project, ret.property.project);
            return ret;
        }
Пример #6
0
        /// <summary>
        /// The final value from prepared information
        /// </summary>
        /// <param name="prepared"></param>
        protected string evaluate(PreparedData prepared)
        {
            string evaluated = String.Empty;

            string custom = customRule(prepared.property.unevaluated, prepared.property.project);
            if(custom != null)
            {
                Log.Trace("Evaluate: custom '{0}'", custom);
                evaluated = evaluate(custom, null);
            }
            else if(prepared.variable.type == PreparedData.ValueType.StringFromDouble
                    || prepared.variable.type == PreparedData.ValueType.StringFromSingle
                    || !String.IsNullOrEmpty(prepared.variable.name))
            {
                //Note: * content from double quotes should be already evaluated in prev. steps.
                //      * content from single quotes shouldn't be evaluated because uses protector for current type above.
                Log.Trace("Evaluate: use content from string or use escaped property");
                evaluated = prepared.property.unevaluated;
            }
            else if(!prepared.property.complex)
            {
                Log.Trace("Evaluate: use getProperty");
                evaluated = getProperty(prepared.property.unevaluated, prepared.property.project);
            }
            else
            {
                Log.Trace("Evaluate: use evaluation with msbuild engine");
                evaluated = evaluate(prepared.property.unevaluated, prepared.property.project);
            }
            Log.Debug("Evaluated: '{0}'", evaluated);

            // alternative to SBE-Scripts
            if(!String.IsNullOrEmpty(prepared.variable.name))
            {
                Log.Debug("Evaluate: ready to define variable - '{0}':'{1}'",
                                                                        prepared.variable.name,
                                                                        prepared.variable.project);

                uvariable.set(prepared.variable.name, prepared.variable.project, evaluated);
                uvariable.evaluate(prepared.variable.name, prepared.variable.project, new EvaluatorBlank(), true);
                evaluated = String.Empty;
            }

            return evaluated;
        }
Пример #7
0
        /// <summary>
        /// Operations for recursive properties and to avoiding some looping.
        ///
        /// The recursive property means that value contains same definition, even after evaluation of this, for example:
        /// `$(var)` -> `value from $(var)` -> `value from value from $(var)` ...
        ///
        /// TODO: I need a COW... fix mooo ~@@``
        /// </summary>
        /// <param name="data">Data with possible recursive property or some looping.</param>
        /// <param name="prepared">Describes property.</param>
        /// <param name="eqEscape">To escape equality if true, otherwise throw PossibleLoopException.</param>
        /// <returns>Evaluated data.</returns>
        protected string unlooping(string data, PreparedData prepared, bool eqEscape)
        {
            string pname = prepared.property.name;

            if (pname == null || data.IndexOf("$(") == -1)
            {
                return(data); // all clear
            }

            HashSet <string> pchecked = new HashSet <string>();
            Action <string>  unlink   = null;

            unlink = delegate(string _name)
            {
                if (!pchecked.Add(_name))
                {
#if DEBUG
                    Log.Debug("unlooping-unlink: has been protected with `{0}`", _name);
#endif
                    return;
                    //throw new MismatchException("");
                }

                if (!references.ContainsKey(_name))
                {
                    return;
                }

                if (references[_name].Contains(pname))
                {
                    throw new LimitException("Found looping for used properties: `{0}` <-> `{1}`", _name, pname);
                }

                foreach (string refvar in references[_name])
                {
                    unlink(refvar);
                }
            };

            data = RPattern.ContainerInNamedCompiled.Replace(data, delegate(Match m)
            {
                string found = m.Groups["name"].Value;

                if (pname == found)
                {
                    if (eqEscape)
                    {
                        return("$" + m.Groups[0].Value);
                    }
                    throw new PossibleLoopException();
                }

                if (!references.ContainsKey(pname))
                {
                    references[pname] = new HashSet <string>();
                }
                references[pname].Add(found);

                // checking
                unlink(found);

                return(m.Groups[0].Value);
            });

            return(data);
        }
Пример #8
0
        /// <summary>
        /// Prepare data for next evaluation step.
        /// </summary>
        /// <param name="raw">a single container e.g.: '(..data..)'</param>
        /// <exception cref="IncorrectSyntaxException"></exception>
        protected PreparedData prepare(string raw)
        {
            Match m = RPattern.PItem.Match(raw.Trim());

            if (!m.Success)
            {
                throw new IncorrectSyntaxException("prepare: failed - '{0}'", raw);
            }

            Group rTSign           = m.Groups["tsign"];
            Group rVSign           = m.Groups["vsign"];
            Group rVariable        = m.Groups[1];
            Group rStringDataD     = m.Groups[2];
            Group rStringDataS     = m.Groups[3];
            Group rDataWithProject = m.Groups[4];
            Group rProject         = m.Groups[5];
            Group rData            = m.Groups[6];

            PreparedData ret = new PreparedData()
            {
                property = new PreparedData.Property()
                {
                    raw = raw
                }
            };

            //Log.Trace("prepare: raw '{0}'", raw);


            /* Variable */

            if (rVariable.Success)
            {
                ret.variable.name = rVariable.Value;

                switch (rTSign.Value)
                {
                case "+": {
                    ret.variable.tSign = PreparedData.TSignType.DefProperty;
                    break;
                }

                case "-": {
                    ret.variable.tSign = PreparedData.TSignType.UndefProperty;
                    break;
                }

                default: {
                    ret.variable.tSign = PreparedData.TSignType.Default;
                    break;
                }
                }

                switch (rVSign.Value)
                {
                case "+": {
                    ret.variable.vSign = PreparedData.VSignType.Increment;
                    break;
                }

                case "-": {
                    ret.variable.vSign = PreparedData.VSignType.Decrement;
                    break;
                }

                default: {
                    ret.variable.vSign = PreparedData.VSignType.Default;
                    break;
                }
                }

                // all $() in right operand cannot be evaluated because it's escaped and already unwrapped property.
                // i.e. this already should be evaluated with prev. steps - because we are moving upward from deepest container !
                Log.Trace($"prepare: variable name = '{ret.variable.name}'; tSign({ret.variable.tSign}), vSign({ret.variable.vSign})");
            }


            /* Data */

            if ((rStringDataD.Success || rStringDataS.Success) &&
                (rData.Success && !String.IsNullOrWhiteSpace(rData.Value)))
            {
                throw new IncorrectSyntaxException("Incorrect composition of data: string with raw data.");
            }

            if (rStringDataD.Success)
            {
                ret.property.unevaluated = parse(Tokens.unescapeQuotes('"', rStringDataD.Value));
                ret.variable.type        = PreparedData.ValueType.StringFromDouble;
            }
            else if (rStringDataS.Success)
            {
                ret.property.unevaluated = Tokens.unescapeQuotes('\'', rStringDataS.Value);
                ret.variable.type        = PreparedData.ValueType.StringFromSingle;
            }
            else
            {
                ret.property.unevaluated = hquotes((rDataWithProject.Success ? rDataWithProject : rData).Value.Trim());
                ret.variable.type        = (rVariable.Success)? PreparedData.ValueType.Unknown : PreparedData.ValueType.Property;

                int lp = ret.property.unevaluated.IndexOf('.');
                ret.property.name = ((lp == -1)? ret.property.unevaluated : ret.property.unevaluated.Substring(0, lp)).Trim();

                //TODO:
                if (ret.property.name.IndexOf('[') != -1)
                {
                    ret.property.name = null; // avoid static methods
                }
            }

            ret.property.complex = !isPropertySimple(ref ret.property.unevaluated);

            Log.Trace($"prepare: value = '{ret.property.unevaluated}'({ret.variable.type}); complex: {ret.property.complex}");

            /* Project */

            if (rDataWithProject.Success)
            {
                string project = rProject.Value.Trim();

                if (rVariable.Success)
                {
                    //TODO: non standard! but it also can be as a $(varname = $($(..data..):project))
                    ret.variable.project = project;
                }
                else
                {
                    ret.property.project = project;
                }
            }

            Log.Trace("prepare: project [v:'{0}'; p:'{1}']", ret.variable.project, ret.property.project);
            return(ret);
        }
 public new string evaluate(PreparedData prepared)
 {
     return base.evaluate(prepared);
 }