|
2 | 2 | using Superpower;
|
3 | 3 | using Superpower.Model;
|
4 | 4 | using Superpower.Parsers;
|
| 5 | +using System.Globalization; |
5 | 6 |
|
6 | 7 | namespace PythonSourceGenerator.Parser;
|
7 | 8 | public static partial class PythonSignatureParser
|
8 | 9 | {
|
| 10 | + public static TextParser<char> UnderScoreOrDigit { get; } = |
| 11 | + Character.Matching(char.IsDigit, "digit").Or(Character.EqualTo('_')); |
| 12 | + |
9 | 13 | public static TextParser<Unit> IntegerConstantToken { get; } =
|
10 | 14 | from sign in Character.EqualTo('-').OptionalOrDefault()
|
11 |
| - from digits in Character.Digit.AtLeastOnce() |
| 15 | + from firstdigit in Character.Digit |
| 16 | + from digits in UnderScoreOrDigit.Many().OptionalOrDefault([]) |
12 | 17 | select Unit.Value;
|
13 | 18 |
|
14 | 19 | public static TextParser<Unit> DecimalConstantToken { get; } =
|
15 |
| - from sign in Character.EqualTo('-').OptionalOrDefault() |
16 |
| - from digits in Character.Digit.Many().OptionalOrDefault(['0']) |
17 |
| - from decimal_ in Character.EqualTo('.') |
18 |
| - from rest in Character.Digit.Many() |
19 |
| - select Unit.Value; |
| 20 | + from sign in Character.EqualTo('-').OptionalOrDefault() |
| 21 | + from first in Character.Digit |
| 22 | + from rest in UnderScoreOrDigit.Or(Character.In('.', 'e', 'E', '+', '-')).IgnoreMany() |
| 23 | + select Unit.Value; |
20 | 24 |
|
21 | 25 | public static TextParser<Unit> HexidecimalConstantToken { get; } =
|
22 | 26 | from prefix in Span.EqualTo("0x")
|
23 |
| - from digits in Character.HexDigit.AtLeastOnce() |
| 27 | + from digits in Character.EqualTo('_').Or(Character.HexDigit).AtLeastOnce() |
24 | 28 | select Unit.Value;
|
25 | 29 |
|
26 | 30 | public static TextParser<Unit> BinaryConstantToken { get; } =
|
27 | 31 | from prefix in Span.EqualTo("0b")
|
28 |
| - from digits in Character.EqualTo('0').Or(Character.EqualTo('1')).AtLeastOnce() |
| 32 | + from digits in Character.In('0', '1', '_').AtLeastOnce() |
29 | 33 | select Unit.Value;
|
30 | 34 |
|
31 | 35 | public static TextParser<Unit> DoubleQuotedStringConstantToken { get; } =
|
@@ -54,31 +58,28 @@ from close in Character.EqualTo('\'')
|
54 | 58 |
|
55 | 59 | public static TokenListParser<PythonSignatureTokens.PythonSignatureToken, PythonConstant> DecimalConstantTokenizer { get; } =
|
56 | 60 | Token.EqualTo(PythonSignatureTokens.PythonSignatureToken.Decimal)
|
57 |
| - .Apply(Numerics.DecimalDouble) |
58 |
| - .Select(d => new PythonConstant(d)) |
| 61 | + .Select(token => new PythonConstant(double.Parse(token.ToStringValue().Replace("_", ""), NumberStyles.Float, CultureInfo.InvariantCulture))) |
59 | 62 | .Named("Decimal Constant");
|
60 | 63 |
|
61 | 64 | public static TokenListParser<PythonSignatureTokens.PythonSignatureToken, PythonConstant> IntegerConstantTokenizer { get; } =
|
62 | 65 | Token.EqualTo(PythonSignatureTokens.PythonSignatureToken.Integer)
|
63 |
| - .Apply(Numerics.IntegerInt64) |
64 |
| - .Select(d => new PythonConstant(d)) |
| 66 | + .Select(d => new PythonConstant(long.Parse(d.ToStringValue().Replace("_", ""), NumberStyles.Integer))) |
65 | 67 | .Named("Integer Constant");
|
66 | 68 |
|
67 | 69 | public static TokenListParser<PythonSignatureTokens.PythonSignatureToken, PythonConstant> HexidecimalIntegerConstantTokenizer { get; } =
|
68 | 70 | Token.EqualTo(PythonSignatureTokens.PythonSignatureToken.HexidecimalInteger)
|
69 |
| - .Apply(ConstantParsers.HexidecimalConstantParser) |
70 |
| - .Select(d => new PythonConstant { Type = PythonConstant.ConstantType.HexidecimalInteger, IntegerValue = (long)d }) |
| 71 | + .Select(d => new PythonConstant { Type = PythonConstant.ConstantType.HexidecimalInteger, IntegerValue = long.Parse(d.ToStringValue().Substring(2).Replace("_", ""), NumberStyles.HexNumber) }) |
71 | 72 | .Named("Hexidecimal Integer Constant");
|
72 |
| - |
| 73 | + |
73 | 74 | public static TokenListParser<PythonSignatureTokens.PythonSignatureToken, PythonConstant> BinaryIntegerConstantTokenizer { get; } =
|
74 | 75 | Token.EqualTo(PythonSignatureTokens.PythonSignatureToken.BinaryInteger)
|
75 |
| - .Apply(ConstantParsers.BinaryConstantParser) |
76 |
| - .Select(d => new PythonConstant { Type = PythonConstant.ConstantType.BinaryInteger, IntegerValue = (long)d }) |
| 76 | + // TODO: Consider Binary Format specifier introduced in .NET 8 https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#binary-format-specifier-b |
| 77 | + .Select(d => new PythonConstant { Type = PythonConstant.ConstantType.BinaryInteger, IntegerValue = (long)Convert.ToUInt64(d.ToStringValue().Substring(2).Replace("_", ""), 2) }) |
77 | 78 | .Named("Binary Integer Constant");
|
78 | 79 |
|
79 | 80 | public static TokenListParser<PythonSignatureTokens.PythonSignatureToken, PythonConstant> BoolConstantTokenizer { get; } =
|
80 | 81 | Token.EqualTo(PythonSignatureTokens.PythonSignatureToken.True).Or(Token.EqualTo(PythonSignatureTokens.PythonSignatureToken.False))
|
81 |
| - .Select(d => new PythonConstant(d.Kind == PythonSignatureTokens.PythonSignatureToken.True )) |
| 82 | + .Select(d => new PythonConstant(d.Kind == PythonSignatureTokens.PythonSignatureToken.True)) |
82 | 83 | .Named("Bool Constant");
|
83 | 84 |
|
84 | 85 | public static TokenListParser<PythonSignatureTokens.PythonSignatureToken, PythonConstant> NoneConstantTokenizer { get; } =
|
@@ -123,15 +124,5 @@ from chars in Character.ExceptIn('\'', '\\')
|
123 | 124 | .Many()
|
124 | 125 | from close in Character.EqualTo('\'')
|
125 | 126 | select new string(chars);
|
126 |
| - |
127 |
| - public static TextParser<UInt64> HexidecimalConstantParser { get; } = |
128 |
| - from prefix in Span.EqualTo("0x") |
129 |
| - from digits in Character.HexDigit.AtLeastOnce() |
130 |
| - select UInt64.Parse(new string(digits), System.Globalization.NumberStyles.HexNumber); |
131 |
| - |
132 |
| - public static TextParser<UInt64> BinaryConstantParser { get; } = |
133 |
| - from prefix in Span.EqualTo("0b") |
134 |
| - from digits in Character.EqualTo('0').Or(Character.EqualTo('1')).AtLeastOnce() |
135 |
| - select Convert.ToUInt64(new string(digits), 2); |
136 | 127 | }
|
137 | 128 | }
|
0 commit comments