예제 #1
0
        private void AddAnyOptions(IteratorExp node)
        {
            if (node.Iterator.Count == 1)
            {
                TranslationOption optionFor = new TranslationOption();
                optionFor.FormatString = string.Format("(for ${0} in {{0}} return if ({{1}}) then ${0} else ())[1]",
                                                       node.Iterator[0].Name);
                optionFor.ParenthesisWhenNotTopLevel = true;
                SubexpressionTranslations.AddTranslationOption(node, optionFor);

                bool canRewrite = true;
                SubexpressionCollector collector = new SubexpressionCollector();
                collector.Visit(node);
                List <LoopExp> loopSubExps = collector.Expressions.OfType <LoopExp>().ToList();
                foreach (LoopExp nestedLoopExp in loopSubExps)
                {
                    collector.Clear();
                    nestedLoopExp.Accept(collector);
                    if (collector.ReferredVariables.Contains(node.Iterator[0]))
                    {
                        canRewrite = false;
                        break;
                    }
                }

                if (canRewrite)
                {
                    TranslationOption optionFilter = new TranslationOption();
                    optionFilter.ContextVariableForSubExpressions = node.Iterator[0];
                    optionFilter.FormatString = string.Format("({{0}}[{{1}}])[1]");
                    optionFilter.ParenthesisWhenNotTopLevel = true;
                    SubexpressionTranslations.AddTranslationOption(node, optionFilter);
                }
            }
        }
예제 #2
0
        public override void Visit(OperationCallExp node)
        {
            if (node.ReferredOperation != null && node.ReferredOperation.Tag is NextOperationTag)
            {
                node.Source.Accept(this);
                TranslationOption option = new TranslationOption();
                option.FormatString = "oclX:apply-templates({0})";
                SubexpressionTranslations.AddTranslationOption(node, option, node.Source);
                return;
            }

            base.Visit(node);

            if (OperationRewritings.IsEmpty())
            {
                OperationRewritings[OperationHelper.firstOperationInfo] = AddFirstRewritings;
                OperationRewritings[OperationHelper.lastOperationInfo]  = AddLastRewritings;
                OperationRewritings[OperationHelper.atOperationInfo]    = AddAtRewritings;
            }

            {
                TranslationOption standardTranslation = SubexpressionTranslations.GetSubexpressionTranslation(node);
                OperationInfo?    operationInfo       = OperationHelper.LookupOperation(node, standardTranslation.OptionsContainer.SubExpressions.ToArray());
                if (operationInfo != null && OperationRewritings.ContainsKey(operationInfo.Value))
                {
                    OperationRewritings[operationInfo.Value](node, operationInfo.Value);
                }
            }
        }
예제 #3
0
        private void AddClosureOptions(IteratorExp node)
        {
            if (node.Iterator.Count == 1)
            {
                if (node.Body is PropertyCallExp)
                {
                    PSMPath path = PSMPathBuilder.BuildPSMPath((PropertyCallExp)node.Body, OclContext, VariableNamer, buildPathParams);

                    // oclX:closure(departments/department, function($c) { $c/subdepartments/department })/name
                    //              departments/department/descendant-or-self::department

                    /*
                     * departments/department + /subdepartments/department
                     */
                    if (PathsJoinable(path, node) && path.IsDownwards && path.Steps.Count > 0)
                    {
                        TranslationOption descendantOption = new TranslationOption();
                        string            lastStep         = path.Steps.Last().ToXPath();
                        if (lastStep.StartsWith("/"))
                        {
                            lastStep = lastStep.Substring(1);
                        }
                        descendantOption.FormatString = string.Format("{{0}}/descendant-or-self::{0}", lastStep);
                        SubexpressionTranslations.AddTranslationOption(node, descendantOption);
                    }
                }
            }
        }
예제 #4
0
        public virtual void Visit(OperationCallExp node)
        {
            AssignIsPartOfIteratorBody(node);
            OclExpression[] arguments = new OclExpression[node.Arguments.Count + 1];
            if (node.Source is PropertyCallExp)
            {
                this.Visit((PropertyCallExp)node.Source, true);
            }
            else
            {
                node.Source.Accept(this);
            }

            arguments[0] = node.Source;
            for (int i = 0; i < node.Arguments.Count; i++)
            {
                if (node.Arguments[i] is PropertyCallExp)
                {
                    this.Visit((PropertyCallExp)node.Arguments[i], true);
                }
                else
                {
                    node.Arguments[i].Accept(this);
                }
                arguments[i + 1] = node.Arguments[i];
            }

            TranslationOption option = new TranslationOption();

            option.FormatString = OperationHelper.CreateBasicFormatString(node, arguments);
            this.SubexpressionTranslations.AddTranslationOption(node, option, arguments);
        }
예제 #5
0
        public override void Visit(IteratorExp node)
        {
            base.Visit(node);
            node.Source.Accept(this);
            loopStack.Push(node);
            node.Body.Accept(this);

            TranslationOption option = new TranslationOption();

            if (node.Iterator.Count == 1)
            {
                option.FormatString = string.Format("oclX:{0}({{0}}, function(${1}) {{{{ {{1}} }}}})", node.IteratorName, node.Iterator[0].Name);
            }
            else
            {
                option.FormatString = string.Format("oclX:{0}N({{0}}, function({1}) {{{{ {{1}} }}}})", node.IteratorName, node.Iterator.ConcatWithSeparator(vd => "$" + vd.Name, ", "));
            }

            loopStack.Pop();

            SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Body);
            if (PredefinedIteratorExpressionRewritings.ContainsKey(node.IteratorName))
            {
                PredefinedIteratorExpressionRewritings[node.IteratorName](node);
            }
        }
예제 #6
0
        public override void Visit(IteratorExp node)
        {
            base.Visit(node);
            node.Source.Accept(this);
            loopStack.Push(node);
            var prevInsideDynamicEvaluation = insideDynamicEvaluation;

            insideDynamicEvaluation = true;
            node.Body.Accept(this);
            insideDynamicEvaluation = prevInsideDynamicEvaluation;

            string apostrophe = insideDynamicEvaluation ? "''" : "'";

            TranslationOption option = new TranslationOption();

            if (node.Iterator.Count == 1)
            {
                option.FormatString = string.Format("oclX:{0}({{0}}, {2}{1}{2}, {2}{{1}}{2}, $variables)", node.IteratorName, node.Iterator[0].Name, apostrophe);
            }
            else
            {
                option.FormatString = string.Format("oclX:{0}N({{0}}, {2}{1}{2}, {2}{{1}}{2}, $variables)", node.IteratorName, node.Iterator.ConcatWithSeparator(vd => vd.Name, ", "), apostrophe);
            }
            SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Body);

            loopStack.Pop();
        }
예제 #7
0
        public virtual void Visit(PropertyCallExp node, bool isOperationArgument)
        {
            AssignIsPartOfIteratorBody(node);
            PSMPath psmPath = PSMPathBuilder.BuildPSMPath(node, OclContext, VariableNamer, buildPathParams);
            string  xpath   = psmPath.ToXPath(delayFirstVariableStep: true);

            if (!isOperationArgument)
            {
                string wrapString = OperationHelper.WrapAtomicOperand(node, null, 0);
                xpath = string.Format(wrapString, xpath);
            }

            var steps = psmPath.Steps.OfType <IPSMPathStepWithCardinality>().Where(s => s.Lower == 0);

            if (steps.Any())
            {
                Log.AddWarningTaggedFormat("Navigation using '{0}' may result in 'null', which will be an empty sequence in XPath. ", node, steps.ConcatWithSeparator(s => s.ToXPath(), ","));
            }

            TranslationOption option = new TranslationOption();

            if (psmPath.StartingVariableExp != null)
            {
                option.ContextVariableSubstitution = true;
                option.StartingVariable            = psmPath.StartingVariableExp.referredVariable;
            }
            option.FormatString = xpath;
            SubexpressionTranslations.AddTranslationOption(node, option, psmPath.SubExpressions.ToArray());
        }
예제 #8
0
        public virtual void Visit(IfExp node)
        {
            node.Condition.Accept(this);
            node.ThenExpression.Accept(this);
            node.ElseExpression.Accept(this);
            TranslationOption option = new TranslationOption();

            option.FormatString = "if ({0}) then {1} else {2}";
            SubexpressionTranslations.AddTranslationOption(node, option, node.Condition, node.ThenExpression, node.ElseExpression);
        }
예제 #9
0
 private void AddExistsOptions(IteratorExp node)
 {
     if (node.Iterator.Count == 1)
     {
         TranslationOption option = new TranslationOption();
         option.ParenthesisWhenNotTopLevel = true;
         option.FormatString = string.Format("some ${0} in {{0}} satisfies {{1}}", node.Iterator[0].Name);
         SubexpressionTranslations.AddTranslationOption(node, option);
     }
 }
예제 #10
0
        public override void Visit(LetExp node)
        {
            base.Visit(node);
            node.Variable.Value.Accept(this);
            node.InExpression.Accept(this);
            TranslationOption translationOption = new TranslationOption();

            translationOption.FormatString = string.Format("for ${0} in {{0}} return {{1}}", node.Variable.Name);
            SubexpressionTranslations.AddTranslationOption(node, translationOption, node.Variable.Value, node.InExpression);
        }
예제 #11
0
        public override void Visit(ClassLiteralExp node)
        {
            base.Visit(node);
            PSMPath psmPath = PSMPathBuilder.BuildPSMPath(node, OclContext, VariableNamer, buildPathParams);
            string  xpath   = psmPath.ToXPath();

            TranslationOption option = new TranslationOption();

            option.FormatString = xpath;
            SubexpressionTranslations.AddTranslationOption(node, option, psmPath.SubExpressions.ToArray());
        }
예제 #12
0
        public TranslationOption GetSubexpressionTranslation(OclExpression expression)
        {
            TranslationOption selectedOption = Translations[expression].Options[SelectedTranslations[expression]];

            if (Log != null && selectedOption.LogMessagesWhenSelected != null)
            {
                foreach (var v in selectedOption.LogMessagesWhenSelected)
                {
                    Log.AddLogMessage(v);
                }
            }
            return(selectedOption);
        }
예제 #13
0
        public override void Visit(IterateExp node)
        {
            base.Visit(node);
            node.Source.Accept(this);
            loopStack.Push(node);
            node.Body.Accept(this);
            node.Result.Value.Accept(this);

            TranslationOption option = new TranslationOption();

            option.FormatString = string.Format("oclX:iterate({{0}}, {{1}}, function(${0}, ${1}) {{{{ {{2}} }}}})", node.Iterator[0].Name, node.Result.Name);
            SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Result.Value, node.Body);

            loopStack.Pop();
        }
예제 #14
0
        public virtual void Visit(VariableExp node)
        {
            AssignIsPartOfIteratorBody(node);
            PSMPath psmPath = PSMPathBuilder.BuildPSMPath(node, OclContext, VariableNamer, buildPathParams);
            string  xpath   = psmPath.ToXPath(delayFirstVariableStep: true);

            TranslationOption option = new TranslationOption();

            if (psmPath.StartingVariableExp != null)
            {
                option.ContextVariableSubstitution = true;
                option.StartingVariable            = psmPath.StartingVariableExp.referredVariable;
            }
            option.FormatString = xpath;
            SubexpressionTranslations.AddTranslationOption(node, option, psmPath.SubExpressions.ToArray());
        }
예제 #15
0
        public void AddTrivialTranslation(OclExpression expression, string translation)
        {
            TranslationOptions options = new TranslationOptions();

            options.Expression = expression;
            options.SubexpressionTranslations = this;
            options.TranslatedExpression      = expression;
            TranslationOption option = new TranslationOption();

            option.OptionsContainer = options;
            option.FormatString     = translation;
            if (this.Translations.ContainsKey(expression))
            {
                throw new InvalidOperationException(string.Format("Expression '{0}' translated reapeatedly. ", expression));
            }
            options.Options.Add(option);
            this.Translations[expression]         = options;
            this.SelectedTranslations[expression] = 0;
        }
예제 #16
0
        public void AddTranslationOption(OclExpression expression, TranslationOption option, params OclExpression[] subExpressions)
        {
            TranslationOptions options;

            if (!this.Translations.ContainsKey(expression))
            {
                options            = new TranslationOptions();
                options.Expression = expression;
                options.SubexpressionTranslations = this;
                options.TranslatedExpression      = expression;
                foreach (OclExpression subExpression in subExpressions)
                {
                    options.SubExpressions.Add(subExpression);
                }
                this.Translations[expression] = options;
            }
            else
            {
                options = this.Translations[expression];
                if (subExpressions != null && subExpressions.Length > 0)
                {
                    if (subExpressions.Length != options.SubExpressions.Count)
                    {
                        throw new InvalidOperationException(string.Format("Inconsistency of subexpressions when adding options for '{0}'", expression));
                    }

                    for (int index = 0; index < subExpressions.Length; index++)
                    {
                        OclExpression subExpression = subExpressions[index];
                        if (subExpression != options.SubExpressions[index])
                        {
                            throw new InvalidOperationException(string.Format("Inconsistency of subexpressions when adding options for '{0}'", expression));
                        }
                    }
                }
            }

            option.OptionsContainer = options;
            this.SelectedTranslations[expression] = 0;
            options.Options.Add(option);
        }
예제 #17
0
        private void AddCollectionAccessRewritings(OperationCallExp operationCallExp, string accesExpr, OperationInfo operationInfo)
        {
            TranslationOption optionIndex = new TranslationOption();

            SubexpressionTranslations.AddTranslationOption(operationCallExp, optionIndex);
            // XPath filter changes context - no variable corresponds to the context in this case
            optionIndex.ContextVariableForSubExpressions = null;
            optionIndex.ContextVariableChangeOnlyIn      = 1;
            // in some special cases, parentheses can be omitted
            bool omitParentheses = false;

            if (operationCallExp.Source is LiteralExp)
            {
                omitParentheses = true;
            }
            if (operationCallExp.Source is VariableExp)
            {
                omitParentheses = true;
            }
            if (!operationInfo.IsXPathInfix && !operationInfo.IsXPathPrefix &&
                !operationInfo.IsAmong(OperationHelper.firstOperationInfo, OperationHelper.lastOperationInfo, OperationHelper.atOperationInfo))
            {
                omitParentheses = true;
            }

            if (omitParentheses)
            {
                optionIndex.FormatString = string.Format("({{0}})[{0}]", accesExpr);
            }
            else
            {
                optionIndex.FormatString = string.Format("({{0}})[{0}]", accesExpr);
            }

            optionIndex.LogMessagesWhenSelected = new List <LogMessage <OclExpression> >();
            optionIndex.LogMessagesWhenSelected.Add(new LogMessage <OclExpression>()
            {
                Tag = operationCallExp, MessageText =
                    "Using indexing returns empty sequence when indexes are out of bounds (no error reported, unlike in OCL). "
            });
        }
예제 #18
0
        public override void Visit(IterateExp node)
        {
            base.Visit(node);
            node.Source.Accept(this);
            loopStack.Push(node);
            node.Result.Value.Accept(this);
            var prevInsideDynamicEvaluation = insideDynamicEvaluation;

            insideDynamicEvaluation = true;
            node.Body.Accept(this);
            insideDynamicEvaluation = prevInsideDynamicEvaluation;

            string            apostrophe = insideDynamicEvaluation ? "''" : "'";
            TranslationOption option     = new TranslationOption();

            option.FormatString = string.Format("oclX:iterate({{0}}, {2}{0}{2}, {2}{1}{2}, {2}{{1}}{2}, {2}{{2}}{2}, $variables)", node.Iterator[0].Name, node.Result.Name, apostrophe);

            loopStack.Pop();

            SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Result.Value, node.Body);
        }
예제 #19
0
        protected override string TupleLiteralToXPath(TupleLiteralExp tupleLiteral, List <OclExpression> subExpressions)
        {
            StringBuilder formatBuilder = new StringBuilder();

            formatBuilder.Append("(map{{");
            foreach (KeyValuePair <string, TupleLiteralPart> kvp in tupleLiteral.Parts)
            {
                kvp.Value.Value.Accept(this);
                formatBuilder.AppendFormat("'{0}' := {{{1}}}, ", kvp.Value.Attribute.Name, subExpressions.Count);
                subExpressions.Add(kvp.Value.Value);
            }
            if (formatBuilder.Length > 0)
            {
                formatBuilder.Length = formatBuilder.Length - 2;
            }
            formatBuilder.Append("}})");
            TranslationOption option = new TranslationOption();

            option.FormatString = formatBuilder.ToString();
            SubexpressionTranslations.AddTranslationOption(tupleLiteral, option, subExpressions.ToArray());
            return(option.FormatString);
        }
예제 #20
0
        private void AddCollectOptions(IteratorExp node)
        {
            if (node.Iterator.Count == 1)
            {
                TranslationOption option = new TranslationOption();
                option.ParenthesisWhenNotTopLevel = true;
                option.FormatString = string.Format("for ${0} in {{0}} return {{1}}", node.Iterator[0].Name);
                SubexpressionTranslations.AddTranslationOption(node, option);

                /* when the body of collect is a navigation that can be chained, replace it */
                if (node.Body is PropertyCallExp)
                {
                    PSMPath path = PSMPathBuilder.BuildPSMPath((PropertyCallExp)node.Body, OclContext, VariableNamer, buildPathParams);
                    if (PathsJoinable(path, node))
                    {
                        TranslationOption option2 = new TranslationOption();
                        option2.FormatString = string.Format("{{0}}{0}", path.ToXPath(withoutFirstStep: true));
                        SubexpressionTranslations.AddTranslationOption(node, option2);
                    }
                }
            }
        }
예제 #21
0
        protected override string ClassLiteralToXPath(ClassLiteralExp tupleLiteral, List <OclExpression> subExpressions)
        {
            StringBuilder formatBuilder = new StringBuilder();
            string        elementName   = EvolutionAssignmentStack.Peek() != null ? (EvolutionAssignmentStack.Peek().PSMAssociation != null ? EvolutionAssignmentStack.Peek().PSMAssociation.Name: string.Empty): string.Empty;

            formatBuilder.AppendFormat("oclX:genericConstructor('{0}', map {{{{", elementName);
            foreach (KeyValuePair <string, TupleLiteralPart> kvp in tupleLiteral.Parts)
            {
                kvp.Value.Value.Accept(this);
                formatBuilder.AppendFormat("'{0}' := {{{1}}}, ", kvp.Key, subExpressions.Count);
                subExpressions.Add(kvp.Value.Value);
            }
            if (formatBuilder.Length > 0)
            {
                formatBuilder.Length = formatBuilder.Length - 2;
            }
            formatBuilder.Append("}} )");
            TranslationOption option = new TranslationOption();

            option.FormatString = formatBuilder.ToString();
            SubexpressionTranslations.AddTranslationOption(tupleLiteral, option, subExpressions.ToArray());
            return(option.FormatString);
        }
예제 #22
0
        private VariableDeclaration FindContextVariable()
        {
            VariableDeclaration result = null;

            TranslationOption co = this.CallingOption;

            while (co != null)
            {
                if (co.ContextVariableForSubExpressions != null &&
                    (co.ContextVariableChangeOnlyIn == -1 || co.ContextVariableChangeOnlyIn == this.SubexpressionIndex))
                {
                    result = co.ContextVariableForSubExpressions;
                    break;
                }

                if (co.CallingOption == null)
                {
                    result = co.OptionsContainer.Expression.ConstraintContext.Self;
                }
                co = co.CallingOption;
            }

            return(result);
        }
예제 #23
0
        public virtual void Visit(CollectionLiteralExp node)
        {
            AssignIsPartOfIteratorBody(node);
            StringBuilder        formatBuilder  = new StringBuilder();
            List <OclExpression> subExpressions = new List <OclExpression>();

            // opening parenthesis of xpath sequence literal
            formatBuilder.Append("(");
            foreach (CollectionLiteralPart clp in node.Parts)
            {
                #region helper function
                Action <OclExpression> appendOne = delegate(OclExpression exp)
                {
                    if (exp is LiteralExp)
                    {
                        formatBuilder.Append("{");
                        formatBuilder.Append(subExpressions.Count);
                        formatBuilder.Append("}");
                    }
                    else
                    {
                        formatBuilder.Append("{(");
                        formatBuilder.Append(subExpressions.Count);
                        formatBuilder.Append(")}");
                    }
                };
                #endregion

                if (clp is CollectionRange)
                {
                    CollectionRange range = ((CollectionRange)clp);
                    range.First.Accept(this);
                    range.Last.Accept(this);

                    appendOne(range.First);
                    subExpressions.Add(range.First);
                    formatBuilder.Append(" to ");
                    appendOne(range.Last);
                    subExpressions.Add(range.Last);
                }

                if (clp is CollectionItem)
                {
                    CollectionItem collectionItem = (CollectionItem)clp;
                    collectionItem.Item.Accept(this);
                    appendOne(collectionItem.Item);
                    subExpressions.Add(collectionItem.Item);
                }
                formatBuilder.Append(", ");
            }

            if (formatBuilder.Length > 1) // remove last comma
            {
                formatBuilder.Length = formatBuilder.Length - 2;
            }

            // closing parenthesis of xpath sequence literal
            formatBuilder.Append(")");

            TranslationOption option = new TranslationOption();
            option.FormatString = formatBuilder.ToString();
            SubexpressionTranslations.AddTranslationOption(node, option, subExpressions.ToArray());
        }
예제 #24
0
        private void AddSelectRejectOptions(IteratorExp node, bool select)
        {
            // select and reject differ only in not() applied in filter
            if (node.Iterator.Count == 1)
            {
                TranslationOption optionFor = new TranslationOption();
                optionFor.ParenthesisWhenNotTopLevel = true;
                if (select)
                {
                    optionFor.FormatString = string.Format("for ${0} in {{0}} return if ({{1}}) then ${0} else ()",
                                                           node.Iterator[0].Name);
                }
                else
                {
                    optionFor.FormatString = string.Format(
                        "for ${0} in {{0}} return if (not({{1}})) then ${0} else ()", node.Iterator[0].Name);
                }
                SubexpressionTranslations.AddTranslationOption(node, optionFor);

                /*
                 * this option can be used only when there is no iterator in body, which references the current iterator variable,
                 * because there is no XPath variable corresponding to the iterator variable (context is used instead).
                 */
                {
                    bool canRewrite = true;
                    SubexpressionCollector collector = new SubexpressionCollector();
                    collector.Visit(node);
                    List <LoopExp> loopSubExps = collector.Expressions.OfType <LoopExp>().ToList();
                    foreach (LoopExp nestedLoopExp in loopSubExps)
                    {
                        collector.Clear();
                        nestedLoopExp.Accept(collector);
                        if (collector.ReferredVariables.Contains(node.Iterator[0]))
                        {
                            canRewrite = false;
                            break;
                        }
                    }

                    if (canRewrite)
                    {
                        TranslationOption optionFilter = new TranslationOption();
                        optionFilter.ContextVariableForSubExpressions = node.Iterator[0];
                        if (select)
                        {
                            optionFilter.FormatString = string.Format("{{0}}[{{1}}]");
                        }
                        else
                        {
                            optionFilter.FormatString = string.Format("{{0}}[not({{1}})]");
                        }
                        SubexpressionTranslations.AddTranslationOption(node, optionFilter);
                    }
                    else // translation with let
                    {
                        TranslationOption optionFilterLet = new TranslationOption();
                        optionFilterLet.ContextVariableForSubExpressions = node.Iterator[0];
                        if (select)
                        {
                            optionFilterLet.FormatString = string.Format("{{0}}[let ${0} := . return {{1}}]",
                                                                         node.Iterator[0].Name);
                        }
                        else
                        {
                            optionFilterLet.FormatString = string.Format("{{0}}[let ${0} := . return not({{1}})]",
                                                                         node.Iterator[0].Name);
                        }
                        SubexpressionTranslations.AddTranslationOption(node, optionFilterLet);
                    }
                }
            }
        }
예제 #25
0
        public string GetString(bool topLevel)
        {
            object[] translatedSubexpressions = new object[OptionsContainer.SubExpressions.Count];
            for (int index = 0; index < OptionsContainer.SubExpressions.Count; index++)
            {
                OclExpression     subExpression = OptionsContainer.SubExpressions[index];
                TranslationOption selectedSubexpressionTranslationOption = OptionsContainer.SubexpressionTranslations.GetSubexpressionTranslation(subExpression);
                foreach (TranslationOption subexpressionTranslationOption in OptionsContainer.SubexpressionTranslations.Translations[subExpression].Options)
                {
                    subexpressionTranslationOption.CallingOption      = this;
                    subexpressionTranslationOption.SubexpressionIndex = index;
                }
                translatedSubexpressions[index] = selectedSubexpressionTranslationOption.GetString(false);
            }

            string result = null;

            if (!ContextVariableSubstitution)
            {
                result = string.Format(FormatString, translatedSubexpressions);
            }
            else
            {
                bool standardVariableTranslation = true;
                if (StartingVariable == FindContextVariable())
                {
                    if (SubexpressionTranslations.XPathContextVariableReplacementMode == SubexpressionTranslations.EContextVariableReplacementMode.AnyContextVariable)
                    {
                        result = string.Format(FormatString, @".");
                        if (result.StartsWith(@"./"))
                        {
                            result = result.Substring(2);
                        }
                        standardVariableTranslation = false;
                    }
                    else //i.e. SubexpressionTranslations.ContextVariableReplacementMode == SubexpressionTranslations.EContextVariableReplacementMode.OutermostSelfOnly
                    {
                        if (!this.OptionsContainer.Expression.IsPartOfIteratorBody && StartingVariable.IsContextVariable)
                        {
                            result = string.Format(FormatString, @".");
                            if (result.StartsWith(@"./"))
                            {
                                result = result.Substring(2);
                            }
                            standardVariableTranslation = false;
                        }
                    }
                }

                if (standardVariableTranslation)
                {
                    result = string.Format(FormatString, "$" + StartingVariable.Name);
                }
            }

            if (ParenthesisWhenNotTopLevel && !topLevel)
            {
                return("(" + result + ")");
            }
            else
            {
                return(result);
            }
        }