Inheritance: Parsed.Object
Ejemplo n.º 1
0
        void BadNestedTerminationHandler(Parsed.Object terminatingObj)
        {
            Conditional conditional = null;

            for (var ancestor = terminatingObj.parent; ancestor != null; ancestor = ancestor.parent)
            {
                if (ancestor is Sequence || ancestor is Conditional)
                {
                    conditional = ancestor as Conditional;
                    break;
                }
            }

            var errorMsg = "Choices nested in conditionals or sequences need to explicitly divert afterwards.";

            // Tutorialise proper choice syntax if this looks like a single choice within a condition, e.g.
            // { condition:
            //      * choice
            // }
            if (conditional != null)
            {
                var numChoices = conditional.FindAll <Choice>().Count;
                if (numChoices == 1)
                {
                    errorMsg = "Choices with conditions should be written: '* {condition} choice'. Otherwise, " + errorMsg.ToLower();
                }
            }

            Error(errorMsg, terminatingObj);
        }
Ejemplo n.º 2
0
        protected Conditional InnerConditionalContent(Expression initialQueryExpression)
        {
            List<ConditionalSingleBranch> alternatives;

            bool canBeInline = initialQueryExpression != null;
            bool isInline = Newline () == null;

            if (isInline && !canBeInline) {
                return null;
            }

            // Inline innards
            if (isInline) {
                alternatives = InlineConditionalBranches ();
            } 

            // Multiline innards
            else {
                alternatives = MultilineConditionalBranches ();
                if (alternatives == null) {

                    // Allow single piece of content within multi-line expression, e.g.:
                    // { true: 
                    //    Some content that isn't preceded by '-'
                    // }
                    if (initialQueryExpression) {
                        List<Parsed.Object> soleContent = StatementsAtLevel (StatementLevel.InnerBlock);
                        if (soleContent != null) {
                            var soleBranch = new ConditionalSingleBranch (soleContent);
                            alternatives = new List<ConditionalSingleBranch> ();
                            alternatives.Add (soleBranch);

                            // Also allow a final "- else:" clause
                            var elseBranch = Parse(SingleMultilineCondition);
                            if (elseBranch) {
                                if (!elseBranch.isElse) {
                                    ErrorWithParsedObject ("Expected an '- else:' clause here rather than an extra condition", elseBranch);
                                    elseBranch.isElse = true;
                                }
                                alternatives.Add (elseBranch);
                            }
                        }
                    }

                    // Still null?
                    if (alternatives == null) {
                        return null;
                    }
                }

                // Like a switch statement
                // { initialQueryExpression:
                //    ... match the expression
                // }
                if (initialQueryExpression) {

                    bool earlierBranchesHaveOwnExpression = false;
                    for (int i = 0; i < alternatives.Count; ++i) {
                        var branch = alternatives [i];
                        bool isLast = (i == alternatives.Count - 1);

                        // Match query
                        if (branch.ownExpression) {
                            branch.shouldMatchEquality = true;
                            earlierBranchesHaveOwnExpression = true;
                        }

                        // Else (final branch)
                        else if (earlierBranchesHaveOwnExpression && isLast) {
                            branch.isElse = true;
                        } 

                        // Binary condition:
                        // { trueOrFalse:
                        //    - when true
                        //    - when false
                        // }
                        else {

                            if (!isLast && alternatives.Count > 2) {
                                ErrorWithParsedObject ("Only final branch can be an 'else'. Did you miss a ':'?", branch);
                            } else {
                                if (i == 0)
                                    branch.isTrueBranch = true;
                                else
                                    branch.isElse = true;
                            }
                        }
                    }
                } 

                // No initial query, so just a multi-line conditional. e.g.:
                // {
                //   - x > 3:  greater than three
                //   - x == 3: equal to three
                //   - x < 3:  less than three
                // }
                else {
                    
                    for (int i = 0; i < alternatives.Count; ++i) {
                        var alt = alternatives [i];
                        bool isLast = (i == alternatives.Count - 1);
                        if (alt.ownExpression == null) {
                            if (isLast) {
                                alt.isElse = true;
                            } else {
                                if (alt.isElse) {
                                    // Do we ALSO have a valid "else" at the end? Let's report the error there.
                                    var finalClause = alternatives [alternatives.Count - 1];
                                    if (finalClause.isElse) {
                                        ErrorWithParsedObject ("Multiple 'else' cases. Can have a maximum of one, at the end.", finalClause);
                                    } else {
                                        ErrorWithParsedObject ("'else' case in conditional should always be the final one", alt);
                                    }
                                } else {
                                    ErrorWithParsedObject ("Branch doesn't have condition. Are you missing a ':'? ", alt);
                                }

                            }
                        }
                    }
                        
                    if (alternatives.Count == 1 && alternatives [0].ownExpression == null) {
                        ErrorWithParsedObject ("Condition block with no conditions", alternatives [0]);
                    }
                }
            }

            // TODO: Come up with water-tight error conditions... it's quite a flexible system!
            // e.g.
            //   - inline conditionals must have exactly 1 or 2 alternatives
            //   - multiline expression shouldn't have mixed existence of branch-conditions?
            if (alternatives == null)
                return null;

            var cond = new Conditional (initialQueryExpression, alternatives);
            return cond;
        }