/// <summary> /// Prepare, parse, and evaluate mixed data through E-MSBuild supported syntax. /// </summary> /// <param name="data">Mixed input data.</param> /// <returns>Evaluated end value.</returns> public string Eval(string data) { if (string.IsNullOrEmpty(data)) { return(string.Empty); // convert to not null value } if (string.IsNullOrWhiteSpace(data)) { return(data); // save all white-space characters } var sh = new StringHandler(); lock (sync) { return(HQuotes ( sh.Recovery ( ContainerIn ( sh.ProtectEscContainer ( sh.ProtectMixedQuotes(data) ), sh, CONTAINERS_LIMIT ) ) )); } }
/// <summary> /// Handler of the general containers. /// Moving upward from deepest container. /// /// $(name) or $(name:scope) or $([MSBuild]::MakeRelative($(path1), ...):scope) .. /// https://msdn.microsoft.com/en-us/library/vstudio/dd633440%28v=vs.120%29.aspx /// </summary> /// <param name="data"></param> /// <param name="sh"></param> /// <param name="limit">Limitation to containers. Aborts if reached.</param> /// <exception cref="LimitException"></exception> /// <returns></returns> private protected string ContainerIn(string data, StringHandler sh, uint limit) { Regex con = Pattern.ContainerInCompiled; int maxRep = 1; // rule of depth, e.g.: $(p1 = $(Platform))$(p2 = $(p1))$(p2) //TODO: it's slowest but fully compatible with classic rules with minimal programming.. so, improve performance references.Clear(); uint step = 0; do { if (step++ > limit) { sh.Flush(); throw new LimitException($"Restriction of supported containers '{limit}' reached. Aborted.", limit); } data = con.Replace ( data, (Match m) => { string raw = m.Groups[1].Value; LSender.Send(this, $"containerIn: raw - `{raw}`", MsgLevel.Trace); return(Evaluate(Prepare(sh.Recovery(raw)))); }, maxRep ); // protect before new checking data = sh.ProtectEscContainer(sh.ProtectMixedQuotes(data)); } while(con.IsMatch(data)); return(data); }