private static Result<Quantity, Error<QuantityError>> GetError(
            ParseSettings parseSettings,
            QuantityError quantityError,
            Lexemes lexemes)
        {
            var error = Error.From(quantityError, lexemes.Current);
            if (parseSettings.ThrowOnError)
            {
                throw new QuantityParseException(error);
            }

            return Result.Error(error);
        }
        private Expression MultiplicativeExpression(Lexemes lexemes, Expression lhs, ParseSettings parseSettings)
        {
            if (lexemes.AcceptToken(Constants.Multiply) || lexemes.AcceptToken(Constants.MultiplyDot)
                || lexemes.AcceptToken(Constants.MultiplyCross))
            {
                var rhs = this.TryMagnitudeExpression(lexemes, parseSettings);
                return this.MultiplicativeExpression(lexemes, new MultiplicationExpression(lhs, rhs), parseSettings);
            }

            if (lexemes.AcceptToken(Constants.Divide))
            {
                var rhs = this.TryMagnitudeExpression(lexemes, parseSettings);
                return this.MultiplicativeExpression(lexemes, new DivisionExpression(lhs, rhs), parseSettings);
            }

            return lhs;
        }
        /// <summary>
        /// Parses the specified lexeme list.
        /// </summary>
        /// <param name="lexemes">The lexemes.</param>
        /// <param name="parseSettings">The parse settings.</param>
        /// <returns>
        /// The parsed expression.
        /// </returns>
        public Result<Expression, Error<ExpressionError>> Parse(Lexemes lexemes, ParseSettings parseSettings)
        {
            try
            {
                var expression = this.Expression(lexemes, parseSettings);
                string token;
                if (parseSettings.AssertEnd && !lexemes.AcceptTokenType(TokenType.End, out token))
                {
                    throw CreateParseException(ExpressionError.EndOfDataNotFound, lexemes.Current);
                }

                return Result.Success(expression);
            }
            catch (ExpressionParseException expressionParseException)
            {
                if (parseSettings.ThrowOnError)
                {
                    throw;
                }

                return Result.Error(expressionParseException.Error);
            }
        }
        /// <summary>
        /// Parses the specified quantity.
        /// </summary>
        /// <param name="lexemes">The lexemes.</param>
        /// <param name="parseSettings">The parse settings.</param>
        /// <returns>
        /// A <see cref="Quantity" />.
        /// </returns>
        /// <exception cref="QuantityParseException">Exception thrown when parsing fails.</exception>
        public Result<Quantity, Error<QuantityError>> Parse(Lexemes lexemes, ParseSettings parseSettings)
        {
            string number;
            if (lexemes.AcceptTokenType(TokenType.Number, out number))
            {
                var value = double.Parse(number, parseSettings.CultureInfo);
                var result = this.expressionParser.Parse(
                    lexemes,
                    new ParseSettings(parseSettings.CultureInfo, false, false));

                if (parseSettings.AssertEnd && lexemes.AcceptTokenType(TokenType.End))
                {
                    return GetError(parseSettings, QuantityError.EndOfDataNotFound, lexemes);
                }

                return Result.For(
                    result,
                    expression => new Quantity(value, this.unitFactory.Create(expression)),
                    error => Error.From(QuantityError.UnitNotFound, lexemes.Current, error));
            }

            return GetError(parseSettings, QuantityError.NumberNotFound, lexemes);
        }
 /// <summary>
 /// Gets the unit.
 /// </summary>
 /// <param name="unit">The unit as a string.</param>
 /// <param name="parseSettings">The parse settings.</param>
 /// <returns>
 /// An <see cref="IUnit" /> based on the specified <see cref="string" />.
 /// </returns>
 public Result<IUnit, Error<ExpressionError>> GetUnit(string unit, ParseSettings parseSettings)
 {
     var result = this.ParseExpression(unit, parseSettings);
     return Result.For(result, this.GetUnit);
 }
        internal Result<Expression, Error<ExpressionError>> ParseExpression(string unit, ParseSettings parseSettings)
        {
            var analysisResult = this.lexicalAnalyzer.Analyze(unit, parseSettings.ThrowOnError);
            if (analysisResult)
            {
                return this.expressionParser.Parse(analysisResult.Value, parseSettings);
            }

            return Result.Error(Error.From(ExpressionError.LexicalAnalysisFailed, null, analysisResult.Error));
        }
 /// <summary>
 /// Gets the specified unit.
 /// </summary>
 /// <param name="unit">The unit.</param>
 /// <param name="parseSettings">The parse settings.</param>
 /// <returns>
 /// An <see cref="IUnit" />.
 /// </returns>
 public static Result<IUnit, Error<ExpressionError>> GetUnitFrom(string unit, ParseSettings parseSettings)
 {
     EnsureInitialization();
     return Instance.GetUnit(unit, parseSettings);
 }
 private Expression TryMultiplicativeExpression(Lexemes lexemes, ParseSettings parseSettings)
 {
     var expression = this.TryMagnitudeExpression(lexemes, parseSettings);
     return this.MultiplicativeExpression(lexemes, expression, parseSettings);
 }
 private Expression Expression(Lexemes lexemes, ParseSettings parseSettings)
 {
     return this.TryMultiplicativeExpression(lexemes, parseSettings);
 }
        private ConstantExpression ConstantExpression(Lexemes lexemes, ParseSettings parseSettings)
        {
            string number;
            if (lexemes.AcceptTokenType(TokenType.Number, out number))
            {
                return new ConstantExpression(double.Parse(number, parseSettings.CultureInfo));
            }

            throw CreateParseException(ExpressionError.NumberNotFound, lexemes.Current);
        }
        private Expression PrimaryExpression(Lexemes lexemes, ParseSettings parseSettings)
        {
            if (lexemes.AcceptToken(Constants.LeftParenthesis))
            {
                var expression = this.Expression(lexemes, parseSettings);
                if (lexemes.AcceptToken(Constants.RightParenthesis))
                {
                    return new ParenthesisExpression(expression);
                }

                throw CreateParseException(ExpressionError.RightParenthesisNotFound, lexemes.Current);
            }

            if (lexemes.AcceptToken(Constants.LeftWeakParenthesis))
            {
                var expression = this.Expression(lexemes, parseSettings);
                if (lexemes.AcceptToken(Constants.RightWeakParenthesis))
                {
                    return expression;
                }

                throw CreateParseException(ExpressionError.RightWeakParenthesisNotFound, lexemes.Current);
            }

            string identifier;
            if (lexemes.AcceptTokenType(TokenType.Identifier, true, out identifier))
            {
                var result = this.unitExpressionParser.Parse(identifier, false);
                if (result)
                {
                    return result.Value;
                }

                throw CreateParseException(ExpressionError.IdentifierNotFound, lexemes.MoveToPrevious(), result.Error);
            }

            return this.ConstantExpression(lexemes, parseSettings);
        }
        private Expression MagnitudeExpression(Lexemes lexemes, Expression lhs, ParseSettings parseSettings)
        {
            if (lexemes.AcceptToken(Constants.Power))
            {
                var constantExpression = this.ConstantExpression(lexemes, parseSettings);
                return this.MagnitudeExpression(
                    lexemes,
                    new MagnitudeExpression(lhs, constantExpression),
                    parseSettings);
            }

            string exponent;
            if (lexemes.AcceptTokenType(TokenType.Exponent, out exponent))
            {
                var constantExpression =
                    new ConstantExpression(
                        double.Parse(CharacterConverter.FromExponentNotation(exponent), parseSettings.CultureInfo));
                return this.MagnitudeExpression(
                    lexemes,
                    new MagnitudeExpression(lhs, constantExpression),
                    parseSettings);
            }

            return lhs;
        }
 private Expression TryMagnitudeExpression(Lexemes lexemes, ParseSettings parseSettings)
 {
     var lhs = this.PrimaryExpression(lexemes, parseSettings);
     return this.MagnitudeExpression(lexemes, lhs, parseSettings);
 }