public void ParseUnitTest() { UnitsCore uc = new UnitsCore(); var cm = new Unit("cm", Dimensions.Length, 0.01); var ft = new Unit("ft", Dimensions.Length, 0.3048); var min = new Unit("min", Dimensions.Time, 60.0); var s = new Unit("s", Dimensions.Time, 1.0); var cfm = new Unit("CFM", ft.Pow(3) / min); uc.RegisterUnit(cm); uc.RegisterUnit(s); var u1 = uc.ParseUnit("cm"); Assert.IsTrue(u1 == cm); var u2 = uc.ParseUnit("cm*cm"); Assert.IsTrue(u2 == cm * cm); var u3 = uc.ParseUnit("cm^2"); Assert.IsTrue(u3 == cm * cm); var u4 = uc.ParseUnit("cm^2.5/cm^1.5"); Assert.IsTrue(u4 == cm); //flow over area -> speed var u5 = uc.ParseUnit("cm^3*s^-1/cm^2"); Assert.IsTrue(u5 == cm / s); }
public Operation Build(IList <Token> tokens, UnitsCore unitsCore) { resultStack.Clear(); operatorStack.Clear(); parameterCount.Clear(); foreach (Token token in tokens) { object value = token.Value; switch (token.TokenType) { case TokenType.Number: resultStack.Push(new FloatingPointConstant((double)token.Value)); break; case TokenType.Text: if (functionRegistry.IsFunctionName((string)token.Value)) { operatorStack.Push(token); parameterCount.Push(1); } else { resultStack.Push(new Variable(((string)token.Value).ToLowerInvariant())); } break; case TokenType.Unit: resultStack.Push(new ChangeUnit(resultStack.Pop(), unitsCore.ParseUnit((string)token.Value))); //perform unit conversion break; case TokenType.LeftBracket: operatorStack.Push(token); break; case TokenType.RightBracket: PopOperations(true, token); //parameterCount.Pop(); break; case TokenType.ArgumentSeparator: PopOperations(false, token); parameterCount.Push(parameterCount.Pop() + 1); break; case TokenType.Operation: Token operation1Token = token; char operation1 = (char)operation1Token.Value; while (operatorStack.Count > 0 && (operatorStack.Peek().TokenType == TokenType.Operation || operatorStack.Peek().TokenType == TokenType.Text)) { Token operation2Token = operatorStack.Peek(); bool isFunctionOnTopOfStack = operation2Token.TokenType == TokenType.Text; if (!isFunctionOnTopOfStack) { char operation2 = (char)operation2Token.Value; if ((IsLeftAssociativeOperation(operation1) && operationPrecedence[operation1] <= operationPrecedence[operation2]) || (operationPrecedence[operation1] < operationPrecedence[operation2])) { operatorStack.Pop(); resultStack.Push(ConvertOperation(operation2Token)); } else { break; } } else { operatorStack.Pop(); resultStack.Push(ConvertFunction(operation2Token)); } } operatorStack.Push(operation1Token); break; } } PopOperations(false, null); VerifyResultStack(); return(resultStack.First()); }