private static MathValue UnrollMathImpl(MathValue value) { var tokens = new List<object>(); Unroll(value, tokens); var outQueue = new Queue<object>(); var opStack = new Stack<Operator>(); foreach (var t in tokens) { if (t is Value) { if (t is GroupedValue) { var grouped = UnrollMath(((GroupedValue)t).Value); outQueue.Enqueue(grouped); continue; } if (t is LeftExistsValue) { var leftExist = new LeftExistsValue(UnrollMath(((LeftExistsValue)t).IfExists)); outQueue.Enqueue(leftExist); continue; } outQueue.Enqueue((Value)t); continue; } var o1 = (Operator)t; while (opStack.Count > 0 && Precedence(o1) <= Precedence(opStack.Peek())) { var o2 = opStack.Pop(); outQueue.Enqueue(o2); } opStack.Push(o1); } while (opStack.Count > 0) { outQueue.Enqueue(opStack.Pop()); } return DeRPN(outQueue); }
internal static Value ParseImpl(ParserStream stream, IPosition forPosition, bool allowSelectorIncludes) { Value ret = null; while (stream.HasMore()) { var c = stream.Peek(); if (char.IsWhiteSpace(c)) { stream.AdvancePastWhiteSpace(); continue; } if (ret != null) { if (c.In('+', '-', '*', '/', '%')) { ret = ParseMathValue(c, ret, stream, forPosition); continue; } if (c == '?') { stream.Advance(); // skip ? if (stream.HasMore() && stream.Peek() == '?') { if (ret == null) { Current.RecordError(ErrorType.Parser, forPosition, "Expected value, found '??'"); throw new StoppedParsingException(); } stream.Advance(); // skip second ? var rhs = ParseImpl(stream, forPosition, allowSelectorIncludes); ret = new MathValue(ret, Operator.Take_Exists, rhs); continue; } ret = new LeftExistsValue(ret); continue; } } if (char.IsDigit(c) || c == '.' || c == '-') { ret = Combine(ret, ParseNumber(stream, forPosition)); continue; } if (c == '(') { ret = Combine(ret, ParseGroup(stream, forPosition)); continue; } if (c.In('\'', '"')) { ret = Combine(ret, ParseQuotedString(c, stream, forPosition)); continue; } if (c == '#') { ret = Combine(ret, ParseHashColor(stream, forPosition)); continue; } if (c == '@') { ret = Combine(ret, ParseFuncValue(stream, forPosition, allowSelectorIncludes)); continue; } ret = Combine(ret, ParseString(stream, forPosition)); } return ret; }