public VariableAssignment (string variableName, Expression assignedExpression) { this.variableName = variableName; // Defensive programming in case parsing of assignedExpression failed if( assignedExpression ) this.expression = AddContent(assignedExpression); }
public Conditional (Expression condition, List<ConditionalSingleBranch> branches) { this.initialCondition = condition; if (this.initialCondition) { AddContent (condition); } this.branches = branches; if (this.branches != null) { AddContent (this.branches.Cast<Parsed.Object> ().ToList ()); } }
protected Expression ExpressionInfixRight(Parsed.Expression left, InfixOperator op) { Whitespace(); var right = Parse(() => Expression(op.precedence)); if (right) { // We assume that the character we use for the operator's type is the same // as that used internally by e.g. Runtime.Expression.Add, Runtime.Expression.Multiply etc var expr = new BinaryExpression(left, right, op.type); return(expr); } return(null); }
public BinaryExpression(Expression left, Expression right, string opName) { leftExpression = AddContent(left); rightExpression = AddContent(right); this.opName = opName; }
public UnaryExpression(Expression inner, string op) { this.innerExpression = AddContent(inner); this.op = op; }
// Attempt to flatten inner expression immediately // e.g. convert (-(5)) into (-5) public static Expression WithInner(Expression inner, string op) { var innerNumber = inner as Number; if( innerNumber ) { if( op == "-" ) { if( innerNumber.value is int ) { return new Number( -((int)innerNumber.value) ); } else if( innerNumber.value is float ) { return new Number( -((float)innerNumber.value) ); } } else if( op == "!" || op == "not" ) { if( innerNumber.value is int ) { return new Number( ((int)innerNumber.value == 0) ? 1 : 0 ); } else if( innerNumber.value is float ) { return new Number( ((float)innerNumber.value == 0.0f) ? 1 : 0 ); } } System.Diagnostics.Debug.Fail ("Unexpected operation or number type"); } // Normal fallback var unary = new UnaryExpression (inner, op); return unary; }
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; }