static void AddAndOr(TagExpression tagExpression, List <TagToken> tokens, List <TagExpression> exprs) { AndOrExpression andOr = tagExpression as AndOrExpression; if (andOr != null) { AddAndOr(andOr.LeftHand, tokens, exprs); tokens.Add(andOr.Token); AddAndOr(andOr.RightHand, tokens, exprs); } else { exprs.Add(tagExpression); } }
internal static TagExpression CompleteExpression(ParserState state) { TagExpression expr = Expr(state); while (state.PeekTokenType() != TagTokenType.AtEof) { TagToken tk = state.NextToken(); switch (tk.TokenType) { case TagTokenType.Or: expr = new AndOrExpression(tk, expr, BooleanExpression(state)); break; case TagTokenType.And: expr = new AndOrExpression(tk, expr, BooleanExpression(state)); break; default: throw new ParserException(string.Format("Unexpected token {0}", tk), tk, state); } } return(expr); }
internal static void ResolveAndOrConflicts(TagExpression expr, ParserState state) { if (expr == null) { throw new ArgumentNullException("expr"); } AndOrExpression andOr = expr as AndOrExpression; if (andOr != null && (andOr.LeftHand is AndOrExpression || andOr.RightHand is AndOrExpression)) { List <TagToken> tokens = new List <TagToken>(); List <TagExpression> exprs = new List <TagExpression>(); AddAndOr(andOr, tokens, exprs); // Create a list of tokens and separating expressions if (exprs.Count != tokens.Count + 1) { throw new InvalidOperationException(); // Not a valid token chain } TagTokenType tt = tokens[0].TokenType; bool hasConflict = false; for (int i = 1; i < tokens.Count; i++) { if (tokens[i].TokenType != tt) { if (!state.Args.ApplyAndOrPriority) { throw new PriorityException("And or conflict; please resolve using parens", tokens[i], state); } else { hasConflict = true; } } } if (hasConflict) { // We re-orden the children to prioritize 'and' above 'or' // We assume: we have at least one 'and' at least one 'or' int i; // Re-create all groups of and-s, from the back while (0 <= (i = LastToken(tokens, TagTokenType.And))) { exprs[i] = new AndOrExpression(tokens[i], exprs[i], exprs[i + 1]); tokens.RemoveAt(i); exprs.RemoveAt(i + 1); } // Re-create all groups of or-s, from the back while (1 <= (i = LastToken(tokens, TagTokenType.Or))) { exprs[i] = new AndOrExpression(tokens[i], exprs[i], exprs[i + 1]); tokens.RemoveAt(i); exprs.RemoveAt(i + 1); } if (exprs.Count != 2 && tokens.Count != 1) { throw new InvalidOperationException(); } andOr.ForceExpression(tokens[0], exprs[0], exprs[1]); } } foreach (TagExpression ee in expr.SubExpressions) { ResolveAndOrConflicts(ee, state); } }