Skip to content

Commit

Permalink
Implement negative hex/binary literals
Browse files Browse the repository at this point in the history
  • Loading branch information
TollyH committed May 18, 2024
1 parent d6afa01 commit 4aa889e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 9 deletions.
31 changes: 23 additions & 8 deletions Assembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,13 @@ public static byte[] ParseLiteral(string operand, bool allowString, out ulong pa
return Encoding.UTF8.GetBytes(str);
}
operand = operand.Replace("_", "");
// Omit any '-' sign when parsing so we can support negative hex and binary literals (-0x & -0b)
bool negative = false;
if (operand[0] == '-')
{
operand = operand[1..];
negative = true;
}
try
{
// Hex (0x), Binary (0b), and Decimal literals are all supported
Expand All @@ -1377,8 +1384,6 @@ public static byte[] ParseLiteral(string operand, bool allowString, out ulong pa
? Convert.ToUInt64(operand[2..], 2)
: operand.Contains('.')
? BitConverter.DoubleToUInt64Bits(Convert.ToDouble(operand))
: operand.StartsWith('-')
? (ulong)Convert.ToInt64(operand)
: Convert.ToUInt64(operand);
}
catch (OverflowException)
Expand All @@ -1387,6 +1392,10 @@ public static byte[] ParseLiteral(string operand, bool allowString, out ulong pa
? string.Format(Strings_Assembler.Error_Literal_Too_Small, long.MinValue, operand)
: string.Format(Strings_Assembler.Error_Literal_Too_Large, ulong.MaxValue, operand));
}
if (negative)
{
parsedNumber = (ulong)-(long)parsedNumber;
}
byte[] result = new byte[8];
BinaryPrimitives.WriteUInt64LittleEndian(result, parsedNumber);
return result;
Expand Down Expand Up @@ -2522,6 +2531,16 @@ private void SetFileMacros()

private static void ValidateNumericLiteral(string operand)
{
if (operand[0] == '-')
{
if (operand.Length == 1)
{
throw new SyntaxError(Strings_Assembler.Error_Literal_Negative_Dash_Only);
}
// Trim the negative sign for the purposes of validation
// - all numeric literals can have it
operand = operand[1..];
}
Match invalidMatch = operand.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
? InvalidHexadecimalChars().Match(operand) // Hex
: operand.StartsWith("0b", StringComparison.OrdinalIgnoreCase)
Expand All @@ -2532,14 +2551,10 @@ private static void ValidateNumericLiteral(string operand)
throw new SyntaxError(string.Format(Strings_Assembler.Error_Literal_Invalid_Character, operand, new string(' ', invalidMatch.Index)));
}
// Edge-case syntax errors not detected by invalid character regular expressions
if ((operand[0] == '.' && operand.Length == 1) || operand == "-.")
if (operand[0] == '.' && operand.Length == 1)
{
throw new SyntaxError(Strings_Assembler.Error_Literal_Floating_Point_Decimal_Only);
}
if (operand[0] == '-' && operand.Length == 1)
{
throw new SyntaxError(Strings_Assembler.Error_Literal_Negative_Dash_Only);
}
if (operand.Equals("0x_", StringComparison.OrdinalIgnoreCase) || operand.Equals("0b_", StringComparison.OrdinalIgnoreCase))
{
throw new SyntaxError(Strings_Assembler.Error_Literal_Underscore_Only);
Expand Down Expand Up @@ -2580,7 +2595,7 @@ private static void ValidateMacroName(string name)
[GeneratedRegex("[^0-1_](?<!^0[bB])")]
private static partial Regex InvalidBinaryChars();

[GeneratedRegex(@"[^0-9_\.](?<!^-)")]
[GeneratedRegex(@"[^0-9_\.]")]
private static partial Regex InvalidDecimalChars();

#if DISPLACEMENT
Expand Down
2 changes: 1 addition & 1 deletion Data.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public enum OperandType
Pointer
}

public enum Register : byte
public enum Register
{
rpo, // Program Offset
rso, // Stack Offset
Expand Down

0 comments on commit 4aa889e

Please sign in to comment.