diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
index 9d55da28..7b36f5e9 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
@@ -82,7 +82,7 @@ public ExpressionParser([CanBeNull] ParameterExpression[] parameters, [NotNull]
_parsingConfig = parsingConfig ?? ParsingConfig.Default;
_keywordsHelper = new KeywordsHelper(_parsingConfig);
- _textParser = new TextParser(expression);
+ _textParser = new TextParser(_parsingConfig, expression);
_methodFinder = new MethodFinder(_parsingConfig);
_expressionHelper = new ExpressionHelper(_parsingConfig);
_typeFinder = new TypeFinder(_parsingConfig, _keywordsHelper);
@@ -843,7 +843,7 @@ Expression ParseIntegerLiteral()
text = text.Substring(2);
}
- if (!ulong.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.CurrentCulture, out ulong value))
+ if (!ulong.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, _parsingConfig.NumberParseCulture, out ulong value))
{
throw ParseError(Res.InvalidIntegerLiteral, text);
}
@@ -872,7 +872,7 @@ Expression ParseIntegerLiteral()
text = text.Substring(3);
}
- if (!long.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.CurrentCulture, out long value))
+ if (!long.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, _parsingConfig.NumberParseCulture, out long value))
{
throw ParseError(Res.InvalidIntegerLiteral, text);
}
@@ -924,7 +924,7 @@ Expression TryParseAsFloat(string text, char qualifier)
{
if (qualifier == 'F' || qualifier == 'f')
{
- if (float.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out float f))
+ if (float.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, _parsingConfig.NumberParseCulture, out float f))
{
return ConstantExpressionHelper.CreateLiteral(f, text);
}
@@ -938,7 +938,7 @@ Expression TryParseAsDecimal(string text, char qualifier)
{
if (qualifier == 'M' || qualifier == 'm')
{
- if (decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out decimal d))
+ if (decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, _parsingConfig.NumberParseCulture, out decimal d))
{
return ConstantExpressionHelper.CreateLiteral(d, text);
}
@@ -953,13 +953,13 @@ Expression TryParseAsDouble(string text, char qualifier)
double d;
if (qualifier == 'D' || qualifier == 'd')
{
- if (double.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out d))
+ if (double.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, _parsingConfig.NumberParseCulture, out d))
{
return ConstantExpressionHelper.CreateLiteral(d, text);
}
}
- if (double.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out d))
+ if (double.TryParse(text, NumberStyles.Number, _parsingConfig.NumberParseCulture, out d))
{
return ConstantExpressionHelper.CreateLiteral(d, text);
}
diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs
index 1633c3ae..3ab902d2 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs
@@ -5,6 +5,17 @@ namespace System.Linq.Dynamic.Core.Parser
{
public class ExpressionPromoter : IExpressionPromoter
{
+ private readonly NumberParser _numberParser;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The ParsingConfig.
+ public ExpressionPromoter(ParsingConfig config)
+ {
+ _numberParser = new NumberParser(config);
+ }
+
///
public virtual Expression Promote(Expression expr, Type type, bool exact, bool convertExpr)
{
@@ -38,7 +49,7 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
- value = TypeHelper.ParseNumber(text, target);
+ value = _numberParser.ParseNumber(text, target);
// Make sure an enum value stays an enum value
if (target.IsEnum)
@@ -48,7 +59,7 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c
break;
case TypeCode.Double:
- if (target == typeof(decimal)) value = TypeHelper.ParseNumber(text, target);
+ if (target == typeof(decimal)) value = _numberParser.ParseNumber(text, target);
break;
case TypeCode.String:
@@ -56,9 +67,9 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c
break;
}
#else
- if (ce.Type == typeof(Int32) || ce.Type == typeof(UInt32) || ce.Type == typeof(Int64) || ce.Type == typeof(UInt64))
+ if (ce.Type == typeof(int) || ce.Type == typeof(uint) || ce.Type == typeof(long) || ce.Type == typeof(ulong))
{
- value = TypeHelper.ParseNumber(text, target);
+ value = _numberParser.ParseNumber(text, target);
// Make sure an enum value stays an enum value
if (target.GetTypeInfo().IsEnum)
@@ -66,14 +77,14 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c
value = Enum.ToObject(target, value);
}
}
- else if (ce.Type == typeof(Double))
+ else if (ce.Type == typeof(double))
{
if (target == typeof(decimal))
{
- value = TypeHelper.ParseNumber(text, target);
+ value = _numberParser.ParseNumber(text, target);
}
}
- else if (ce.Type == typeof(String))
+ else if (ce.Type == typeof(string))
{
value = TypeHelper.ParseEnum(text, target);
}
diff --git a/src/System.Linq.Dynamic.Core/Parser/NumberParser.cs b/src/System.Linq.Dynamic.Core/Parser/NumberParser.cs
new file mode 100644
index 00000000..4557332a
--- /dev/null
+++ b/src/System.Linq.Dynamic.Core/Parser/NumberParser.cs
@@ -0,0 +1,110 @@
+namespace System.Linq.Dynamic.Core.Parser
+{
+ ///
+ /// NumberParser
+ ///
+ public class NumberParser
+ {
+ private readonly ParsingConfig _config;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The ParsingConfig.
+ public NumberParser(ParsingConfig config)
+ {
+ _config = config;
+ }
+
+ ///
+ /// Parses the number (text) into the specified type.
+ ///
+ /// The text.
+ /// The type.
+ public object ParseNumber(string text, Type type)
+ {
+ try
+ {
+#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
+ switch (Type.GetTypeCode(TypeHelper.GetNonNullableType(type)))
+ {
+ case TypeCode.SByte:
+ return sbyte.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Byte:
+ return byte.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Int16:
+ return short.Parse(text, _config.NumberParseCulture);
+ case TypeCode.UInt16:
+ return ushort.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Int32:
+ return int.Parse(text, _config.NumberParseCulture);
+ case TypeCode.UInt32:
+ return uint.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Int64:
+ return long.Parse(text, _config.NumberParseCulture);
+ case TypeCode.UInt64:
+ return ulong.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Single:
+ return float.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Double:
+ return double.Parse(text, _config.NumberParseCulture);
+ case TypeCode.Decimal:
+ return decimal.Parse(text, _config.NumberParseCulture);
+ }
+#else
+ var tp = TypeHelper.GetNonNullableType(type);
+ if (tp == typeof(sbyte))
+ {
+ return sbyte.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(byte))
+ {
+ return byte.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(short))
+ {
+ return short.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(ushort))
+ {
+ return ushort.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(int))
+ {
+ return int.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(uint))
+ {
+ return uint.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(long))
+ {
+ return long.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(ulong))
+ {
+ return ulong.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(float))
+ {
+ return float.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(double))
+ {
+ return double.Parse(text, _config.NumberParseCulture);
+ }
+ if (tp == typeof(decimal))
+ {
+ return decimal.Parse(text, _config.NumberParseCulture);
+ }
+#endif
+ }
+ catch
+ {
+ return null;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/System.Linq.Dynamic.Core/Parser/TypeHelper.cs b/src/System.Linq.Dynamic.Core/Parser/TypeHelper.cs
index a234fe5a..7cde8f2d 100644
--- a/src/System.Linq.Dynamic.Core/Parser/TypeHelper.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/TypeHelper.cs
@@ -185,52 +185,52 @@ public static bool IsCompatibleWith(Type source, Type target)
{
return false;
}
- Type sc = st.GetTypeInfo().IsEnum ? typeof(Object) : st;
- Type tc = tt.GetTypeInfo().IsEnum ? typeof(Object) : tt;
+ Type sc = st.GetTypeInfo().IsEnum ? typeof(object) : st;
+ Type tc = tt.GetTypeInfo().IsEnum ? typeof(object) : tt;
- if (sc == typeof(SByte))
+ if (sc == typeof(sbyte))
{
- if (tc == typeof(SByte) || tc == typeof(Int16) || tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(sbyte) || tc == typeof(short) || tc == typeof(int) || tc == typeof(long) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(Byte))
+ else if (sc == typeof(byte))
{
- if (tc == typeof(Byte) || tc == typeof(Int16) || tc == typeof(UInt16) || tc == typeof(Int32) || tc == typeof(UInt32) || tc == typeof(Int64) || tc == typeof(UInt64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(byte) || tc == typeof(short) || tc == typeof(ushort) || tc == typeof(int) || tc == typeof(uint) || tc == typeof(long) || tc == typeof(ulong) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(Int16))
+ else if (sc == typeof(short))
{
- if (tc == typeof(Int16) || tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(short) || tc == typeof(int) || tc == typeof(long) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(UInt16))
+ else if (sc == typeof(ushort))
{
- if (tc == typeof(UInt16) || tc == typeof(Int32) || tc == typeof(UInt32) || tc == typeof(Int64) || tc == typeof(UInt64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(ushort) || tc == typeof(int) || tc == typeof(uint) || tc == typeof(long) || tc == typeof(ulong) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(Int32))
+ else if (sc == typeof(int))
{
- if (tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(int) || tc == typeof(long) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(UInt32))
+ else if (sc == typeof(uint))
{
- if (tc == typeof(UInt32) || tc == typeof(Int64) || tc == typeof(UInt64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(uint) || tc == typeof(long) || tc == typeof(ulong) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(Int64))
+ else if (sc == typeof(long))
{
- if (tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(long) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(UInt64))
+ else if (sc == typeof(ulong))
{
- if (tc == typeof(UInt64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
+ if (tc == typeof(ulong) || tc == typeof(float) || tc == typeof(double) || tc == typeof(decimal))
return true;
}
- else if (sc == typeof(Single))
+ else if (sc == typeof(float))
{
- if (tc == typeof(Single) || tc == typeof(Double))
+ if (tc == typeof(float) || tc == typeof(double))
return true;
}
@@ -313,11 +313,11 @@ private static int GetNumericTypeKind(Type type)
return 0;
}
- if (type == typeof(Char) || type == typeof(Single) || type == typeof(Double) || type == typeof(Decimal))
+ if (type == typeof(char) || type == typeof(float) || type == typeof(double) || type == typeof(decimal))
return 1;
- if (type == typeof(SByte) || type == typeof(Int16) || type == typeof(Int32) || type == typeof(Int64))
+ if (type == typeof(sbyte) || type == typeof(short) || type == typeof(int) || type == typeof(long))
return 2;
- if (type == typeof(Byte) || type == typeof(UInt16) || type == typeof(UInt32) || type == typeof(UInt64))
+ if (type == typeof(byte) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong))
return 3;
return 0;
@@ -390,117 +390,6 @@ private static void AddInterface(List types, Type type)
}
}
- public static object ParseNumber(string text, Type type)
- {
-#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
- switch (Type.GetTypeCode(GetNonNullableType(type)))
- {
- case TypeCode.SByte:
- sbyte sb;
- if (SByte.TryParse(text, out sb)) return sb;
- break;
- case TypeCode.Byte:
- byte b;
- if (Byte.TryParse(text, out b)) return b;
- break;
- case TypeCode.Int16:
- short s;
- if (Int16.TryParse(text, out s)) return s;
- break;
- case TypeCode.UInt16:
- ushort us;
- if (UInt16.TryParse(text, out us)) return us;
- break;
- case TypeCode.Int32:
- int i;
- if (Int32.TryParse(text, out i)) return i;
- break;
- case TypeCode.UInt32:
- uint ui;
- if (UInt32.TryParse(text, out ui)) return ui;
- break;
- case TypeCode.Int64:
- long l;
- if (Int64.TryParse(text, out l)) return l;
- break;
- case TypeCode.UInt64:
- ulong ul;
- if (UInt64.TryParse(text, out ul)) return ul;
- break;
- case TypeCode.Single:
- float f;
- if (Single.TryParse(text, out f)) return f;
- break;
- case TypeCode.Double:
- double d;
- if (Double.TryParse(text, out d)) return d;
- break;
- case TypeCode.Decimal:
- decimal e;
- if (Decimal.TryParse(text, out e)) return e;
- break;
- }
-#else
- var tp = GetNonNullableType(type);
- if (tp == typeof(SByte))
- {
- sbyte sb;
- if (sbyte.TryParse(text, out sb)) return sb;
- }
- else if (tp == typeof(Byte))
- {
- byte b;
- if (byte.TryParse(text, out b)) return b;
- }
- else if (tp == typeof(Int16))
- {
- short s;
- if (short.TryParse(text, out s)) return s;
- }
- else if (tp == typeof(UInt16))
- {
- ushort us;
- if (ushort.TryParse(text, out us)) return us;
- }
- else if (tp == typeof(Int32))
- {
- int i;
- if (int.TryParse(text, out i)) return i;
- }
- else if (tp == typeof(UInt32))
- {
- uint ui;
- if (uint.TryParse(text, out ui)) return ui;
- }
- else if (tp == typeof(Int64))
- {
- long l;
- if (long.TryParse(text, out l)) return l;
- }
- else if (tp == typeof(UInt64))
- {
- ulong ul;
- if (ulong.TryParse(text, out ul)) return ul;
- }
- else if (tp == typeof(Single))
- {
- float f;
- if (float.TryParse(text, out f)) return f;
- }
- else if (tp == typeof(Double))
- {
- double d;
- if (double.TryParse(text, out d)) return d;
- }
- else if (tp == typeof(Decimal))
- {
- decimal e;
- if (decimal.TryParse(text, out e)) return e;
- }
-#endif
- return null;
- }
-
public static object ParseEnum(string value, Type type)
{
if (type.GetTypeInfo().IsEnum && Enum.IsDefined(type, value))
diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
index 4651a35d..4ad9bea7 100644
--- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs
+++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
@@ -1,4 +1,5 @@
-using System.Linq.Dynamic.Core.CustomTypeProviders;
+using System.Globalization;
+using System.Linq.Dynamic.Core.CustomTypeProviders;
using System.Linq.Dynamic.Core.Parser;
namespace System.Linq.Dynamic.Core
@@ -56,10 +57,7 @@ public IDynamicLinkCustomTypeProvider CustomTypeProvider
///
public IExpressionPromoter ExpressionPromoter
{
- get
- {
- return _expressionPromoter ?? (_expressionPromoter = new ExpressionPromoter());
- }
+ get => _expressionPromoter ?? (_expressionPromoter = new ExpressionPromoter(this));
set
{
@@ -168,5 +166,12 @@ public IQueryableAnalyzer QueryableAnalyzer
/// Default value is false.
///
public bool DateTimeIsParsedAsUTC { get; set; } = false;
+
+ ///
+ /// The number parsing culture.
+ ///
+ /// Default value is CultureInfo.InvariantCulture
+ ///
+ public CultureInfo NumberParseCulture { get; set; } = CultureInfo.InvariantCulture;
}
}
diff --git a/src/System.Linq.Dynamic.Core/Tokenizer/TextParser.cs b/src/System.Linq.Dynamic.Core/Tokenizer/TextParser.cs
index e4c821eb..8f63cc0d 100644
--- a/src/System.Linq.Dynamic.Core/Tokenizer/TextParser.cs
+++ b/src/System.Linq.Dynamic.Core/Tokenizer/TextParser.cs
@@ -6,12 +6,12 @@ namespace System.Linq.Dynamic.Core.Tokenizer
{
internal class TextParser
{
- private static char NumberDecimalSeparator = '.';
+ private const char DefaultNumberDecimalSeparator = '.';
- private static char[] EscapeCharacters = new[] { '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v' };
+ private static readonly char[] EscapeCharacters = new[] { '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v' };
// These aliases are supposed to simply the where clause and make it more human readable
- private static readonly Dictionary _predefinedOperatorAliases = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ private static readonly Dictionary PredefinedOperatorAliases = new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{ "eq", TokenId.Equal },
{ "equal", TokenId.Equal },
@@ -34,6 +34,8 @@ internal class TextParser
{ "mod", TokenId.Percent }
};
+ private readonly ParsingConfig _config;
+ private readonly char _numberDecimalSeparator;
private readonly string _text;
private readonly int _textLen;
@@ -41,10 +43,14 @@ internal class TextParser
private char _ch;
public Token CurrentToken;
- public TextParser(string text)
+ public TextParser(ParsingConfig config, string text)
{
+ _config = config;
+ _numberDecimalSeparator = config.NumberParseCulture?.NumberFormat.NumberDecimalSeparator[0] ?? DefaultNumberDecimalSeparator;
+
_text = text;
_textLen = _text.Length;
+
SetTextPos(0);
NextToken();
}
@@ -63,6 +69,7 @@ private void NextChar()
}
_ch = _textPos < _textLen ? _text[_textPos] : '\0';
}
+
public char PeekNextChar()
{
if (_textPos + 1 < _textLen)
@@ -362,7 +369,7 @@ public void NextToken()
break;
}
- if (_ch == NumberDecimalSeparator)
+ if (_ch == _numberDecimalSeparator)
{
tokenId = TokenId.RealLiteral;
NextChar();
@@ -458,7 +465,7 @@ private static Exception ParseError(int pos, string format, params object[] args
private static TokenId GetAliasedTokenId(TokenId tokenId, string alias)
{
- return tokenId == TokenId.Identifier && _predefinedOperatorAliases.TryGetValue(alias, out TokenId id) ? id : tokenId;
+ return tokenId == TokenId.Identifier && PredefinedOperatorAliases.TryGetValue(alias, out TokenId id) ? id : tokenId;
}
private static bool IsHexChar(char c)
diff --git a/test/System.Linq.Dynamic.Core.Tests/Parser/NumberParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/NumberParserTests.cs
new file mode 100644
index 00000000..79450df8
--- /dev/null
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/NumberParserTests.cs
@@ -0,0 +1,42 @@
+using System.Globalization;
+using NFluent;
+using System.Linq.Dynamic.Core.Parser;
+using Xunit;
+
+namespace System.Linq.Dynamic.Core.Tests.Parser
+{
+ public class NumberParserTests
+ {
+ private readonly ParsingConfig _parsingConfig = new ParsingConfig();
+
+ private readonly NumberParser _sut;
+
+ public NumberParserTests()
+ {
+ _sut = new NumberParser(_parsingConfig);
+ }
+
+ [Fact]
+ public void NumberParser_ParseNumber_Decimal_With_DefaultCulture()
+ {
+ // Act
+ var result = _sut.ParseNumber("3.21", typeof(decimal));
+
+ // Assert
+ Check.That(result).Equals(3.21m);
+ }
+
+ [Fact]
+ public void NumberParser_ParseNumber_Decimal_With_GermanCulture()
+ {
+ // Assign
+ _parsingConfig.NumberParseCulture = CultureInfo.CreateSpecificCulture("de-DE");
+
+ // Act
+ var result = _sut.ParseNumber("3,21", typeof(decimal));
+
+ // Assert
+ Check.That(result).Equals(3.21m);
+ }
+ }
+}
diff --git a/test/System.Linq.Dynamic.Core.Tests/Tokenizer/TextParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/Tokenizer/TextParserTests.cs
index de4448ed..e67bed2c 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Tokenizer/TextParserTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Tokenizer/TextParserTests.cs
@@ -1,4 +1,5 @@
using NFluent;
+using System.Globalization;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Tokenizer;
using Xunit;
@@ -7,11 +8,13 @@ namespace System.Linq.Dynamic.Core.Tests.Tokenizer
{
public class TextParserTests
{
+ private readonly ParsingConfig _config = new ParsingConfig();
+
[Fact]
public void TextParser_Parse_Bar()
{
// Assign + Act
- var textParser = new TextParser(" | ");
+ var textParser = new TextParser(_config, " | ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.Bar);
@@ -23,7 +26,7 @@ public void TextParser_Parse_Bar()
public void TextParser_Parse_Colon()
{
// Assign + Act
- var textParser = new TextParser(" : ");
+ var textParser = new TextParser(_config, " : ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.Colon);
@@ -35,7 +38,7 @@ public void TextParser_Parse_Colon()
public void TextParser_Parse_Exclamation()
{
// Assign + Act
- var textParser = new TextParser(" !x");
+ var textParser = new TextParser(_config, " !x");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.Exclamation);
@@ -47,7 +50,7 @@ public void TextParser_Parse_Exclamation()
public void TextParser_Parse_ExclamationEqual()
{
// Assign + Act
- var textParser = new TextParser(" != 1");
+ var textParser = new TextParser(_config, " != 1");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.ExclamationEqual);
@@ -59,7 +62,7 @@ public void TextParser_Parse_ExclamationEqual()
public void TextParser_Parse_GreaterThanEqual()
{
// Assign + Act
- var textParser = new TextParser(" >= ");
+ var textParser = new TextParser(_config, " >= ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.GreaterThanEqual);
@@ -71,21 +74,21 @@ public void TextParser_Parse_GreaterThanEqual()
public void TextParser_Parse_HexadecimalIntegerLiteral()
{
// Assign + Act
- var textParser = new TextParser(" 0x1234567890AbCdEfL ");
+ var textParser = new TextParser(_config, " 0x1234567890AbCdEfL ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.IntegerLiteral);
Check.That(textParser.CurrentToken.Pos).Equals(1);
Check.That(textParser.CurrentToken.Text).Equals("0x1234567890AbCdEfL");
- Check.ThatCode(() => new TextParser("0xz1234")).Throws();
+ Check.ThatCode(() => new TextParser(_config, "0xz1234")).Throws();
}
[Fact]
public void TextParser_Parse_LessGreater()
{
// Assign + Act
- var textParser = new TextParser(" <> ");
+ var textParser = new TextParser(_config, " <> ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.LessGreater);
@@ -97,7 +100,7 @@ public void TextParser_Parse_LessGreater()
public void TextParser_Parse_NullPropagation()
{
// Assign + Act
- var textParser = new TextParser(" ?. ");
+ var textParser = new TextParser(_config, " ?. ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.NullPropagation);
@@ -109,21 +112,21 @@ public void TextParser_Parse_NullPropagation()
public void TextParser_Parse_RealLiteral()
{
// Assign + Act
- var textParser = new TextParser(" 1.0E25 ");
+ var textParser = new TextParser(_config, " 1.0E25 ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.RealLiteral);
Check.That(textParser.CurrentToken.Pos).Equals(1);
Check.That(textParser.CurrentToken.Text).Equals("1.0E25");
- Check.ThatCode(() => new TextParser("1.e25")).Throws();
+ Check.ThatCode(() => new TextParser(_config, "1.e25")).Throws();
}
[Fact]
public void TextParser_Parse_RealLiteralDecimalQualifier()
{
// Assign + Act
- var textParser = new TextParser(" 12.5m ");
+ var textParser = new TextParser(_config, " 12.5m ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.RealLiteral);
@@ -131,11 +134,29 @@ public void TextParser_Parse_RealLiteralDecimalQualifier()
Check.That(textParser.CurrentToken.Text).Equals("12.5m");
}
+ [Fact]
+ public void TextParser_Parse_RealLiteralDecimalQualifier_Other_NumberDecimalSeparator()
+ {
+ // Assign
+ var config = new ParsingConfig
+ {
+ NumberParseCulture = CultureInfo.CreateSpecificCulture("de-DE")
+ };
+
+ // Act
+ var textParser = new TextParser(config, " 12,5m ");
+
+ // Assert
+ Check.That(textParser.CurrentToken.Id).Equals(TokenId.RealLiteral);
+ Check.That(textParser.CurrentToken.Pos).Equals(1);
+ Check.That(textParser.CurrentToken.Text).Equals("12,5m");
+ }
+
[Fact]
public void TextParser_Parse_RealLiteralFloatQualifier()
{
// Assign + Act
- var textParser = new TextParser(" 12.5f ");
+ var textParser = new TextParser(_config, " 12.5f ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.RealLiteral);
@@ -147,7 +168,7 @@ public void TextParser_Parse_RealLiteralFloatQualifier()
public void TextParser_Parse_RealLiteralMinus()
{
// Assign + Act
- var textParser = new TextParser(" 1.0E-25 ");
+ var textParser = new TextParser(_config, " 1.0E-25 ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.RealLiteral);
@@ -159,7 +180,7 @@ public void TextParser_Parse_RealLiteralMinus()
public void TextParser_Parse_RealLiteralPlus()
{
// Assign + Act
- var textParser = new TextParser(" 1.0E+25 ");
+ var textParser = new TextParser(_config, " 1.0E+25 ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.RealLiteral);
@@ -171,7 +192,7 @@ public void TextParser_Parse_RealLiteralPlus()
public void TextParser_Parse_Percent()
{
// Assign + Act
- var textParser = new TextParser(" % ");
+ var textParser = new TextParser(_config, " % ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.Percent);
@@ -183,7 +204,7 @@ public void TextParser_Parse_Percent()
public void TextParser_Parse_Slash()
{
// Assign + Act
- var textParser = new TextParser(" / ");
+ var textParser = new TextParser(_config, " / ");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.Slash);
@@ -195,7 +216,7 @@ public void TextParser_Parse_Slash()
public void TextParser_Parse_StringLiteral_WithSingleQuotes_Backslash()
{
// Assign + Act
- var textParser = new TextParser("'\\'");
+ var textParser = new TextParser(_config, "'\\'");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.StringLiteral);
@@ -207,7 +228,7 @@ public void TextParser_Parse_StringLiteral_WithSingleQuotes_Backslash()
public void TextParser_Parse_StringLiteral_WithSingleQuotes_DoubleQuote()
{
// Assign + Act
- var textParser = new TextParser("'\"'");
+ var textParser = new TextParser(_config, "'\"'");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.StringLiteral);
@@ -219,7 +240,7 @@ public void TextParser_Parse_StringLiteral_WithSingleQuotes_DoubleQuote()
public void TextParser_Parse_StringLiteral_WithSingleQuotes_SingleQuote()
{
// Assign + Act
- var textParser = new TextParser("'\''");
+ var textParser = new TextParser(_config, "'\''");
// Assert
Check.That(textParser.CurrentToken.Id).Equals(TokenId.StringLiteral);
@@ -232,7 +253,7 @@ public void TextParser_Parse_ThrowsException()
{
// Assign + Act + Assert
//Check.ThatCode(() => { new TextParser("ಬಾ"); }).Throws();
- Check.ThatCode(() => { new TextParser(";"); }).Throws();
+ Check.ThatCode(() => { new TextParser(_config, ";"); }).Throws();
}
}
}