This commit is contained in:
nub31
2025-10-31 11:59:53 +01:00
parent c764857561
commit 031b118a24
14 changed files with 1143 additions and 995 deletions

View File

@@ -423,7 +423,7 @@ public sealed class Parser
case Symbol.Pipe:
binaryExpressionOperator = BinaryOperatorSyntax.BitwiseOr;
return true;
case Symbol.Caret:
case Symbol.XOr:
binaryExpressionOperator = BinaryOperatorSyntax.BitwiseXor;
return true;
default:
@@ -445,6 +445,7 @@ public sealed class Parser
IdentifierToken identifier => ParseIdentifier(startIndex, identifier),
SymbolToken symbolToken => symbolToken.Symbol switch
{
Symbol.Ampersand => new AddressOfSyntax(GetTokens(startIndex), ParsePrimaryExpression()),
Symbol.OpenParen => ParseParenthesizedExpression(),
Symbol.Minus => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Negate, ParsePrimaryExpression()),
Symbol.Bang => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Invert, ParsePrimaryExpression()),
@@ -517,12 +518,6 @@ public sealed class Parser
var startIndex = _tokenIndex;
while (HasToken)
{
if (TryExpectSymbol(Symbol.Ampersand))
{
expr = new AddressOfSyntax(GetTokens(startIndex), expr);
continue;
}
if (TryExpectSymbol(Symbol.Caret))
{
expr = new DereferenceSyntax(GetTokens(startIndex), expr);

View File

@@ -14,14 +14,29 @@ public record IdentifierToken(SourceSpan Span, string Value) : Token(Span)
public record IntLiteralToken(SourceSpan Span, string Value, int Base) : Token(Span)
{
public ulong AsU64 => Convert.ToUInt64(Value, Base);
public long AsI64 => Convert.ToInt64(Value, Base);
public uint AsU32 => Convert.ToUInt32(Value, Base);
public int AsI32 => Convert.ToInt32(Value, Base);
public ushort AsU16 => Convert.ToUInt16(Value, Base);
public short AsI16 => Convert.ToInt16(Value, Base);
public byte AsU8 => Convert.ToByte(Value, Base);
public sbyte AsI8 => Convert.ToSByte(Value, Base);
private string GetNumericValue()
{
// Strip base prefixes: 0b, 0o, 0x
return Base switch
{
2 when Value.StartsWith("0b", StringComparison.OrdinalIgnoreCase)
=> Value.Substring(2),
8 when Value.StartsWith("0o", StringComparison.OrdinalIgnoreCase)
=> Value.Substring(2),
16 when Value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
=> Value.Substring(2),
_ => Value
};
}
public ulong AsU64 => Convert.ToUInt64(GetNumericValue(), Base);
public long AsI64 => Convert.ToInt64(GetNumericValue(), Base);
public uint AsU32 => Convert.ToUInt32(GetNumericValue(), Base);
public int AsI32 => Convert.ToInt32(GetNumericValue(), Base);
public ushort AsU16 => Convert.ToUInt16(GetNumericValue(), Base);
public short AsI16 => Convert.ToInt16(GetNumericValue(), Base);
public byte AsU8 => Convert.ToByte(GetNumericValue(), Base);
public sbyte AsI8 => Convert.ToSByte(GetNumericValue(), Base);
public float AsF32 => Convert.ToSingle(AsI32);
public double AsF64 => Convert.ToDouble(AsI64);
@@ -119,6 +134,7 @@ public enum Symbol
Pipe,
And,
Or,
XOr,
At,
QuestionMark,
}

View File

@@ -68,19 +68,17 @@ public sealed class Tokenizer
private Token ParseToken(char current, int lineStart, int columnStart)
{
// Numbers
if (char.IsDigit(current))
{
return ParseNumber(lineStart, columnStart);
}
// String literals
if (current == '"')
{
return ParseString(lineStart, columnStart);
}
// Try keywords and symbols by length (longest first)
// note(nub31): Look for keywords (longest first in case a keyword fits partially in a larger keyword)
for (var i = 8; i >= 1; i--)
{
if (TryMatchSymbol(i, lineStart, columnStart, out var token))
@@ -89,7 +87,6 @@ public sealed class Tokenizer
}
}
// Identifiers
if (char.IsLetter(current) || current == '_')
{
return ParseIdentifier(lineStart, columnStart);
@@ -103,7 +100,7 @@ public sealed class Tokenizer
var start = _index;
var current = _content[_index];
// Hex literal
// note(nub31): 0xFFFFFF
if (current == '0' && _index + 1 < _content.Length && _content[_index + 1] == 'x')
{
Next(2);
@@ -128,7 +125,7 @@ public sealed class Tokenizer
16);
}
// Binary literal
// note(nub31): 0b11001100
if (current == '0' && _index + 1 < _content.Length && _content[_index + 1] == 'b')
{
Next(2);
@@ -153,7 +150,7 @@ public sealed class Tokenizer
2);
}
// Decimal or float
// note(nub31): 23/23.5
var isFloat = false;
while (_index < _content.Length)
{
@@ -191,7 +188,7 @@ public sealed class Tokenizer
private StringLiteralToken ParseString(int lineStart, int columnStart)
{
Next(); // Skip opening quote
Next();
var start = _index;
while (true)
@@ -236,6 +233,20 @@ public sealed class Tokenizer
var span = _content.AsSpan(_index, length);
if (span is "true")
{
Next(4);
token = new BoolLiteralToken(CreateSpan(lineStart, columnStart), true);
return true;
}
if (span is "false")
{
Next(5);
token = new BoolLiteralToken(CreateSpan(lineStart, columnStart), false);
return true;
}
var symbol = length switch
{
8 => span switch
@@ -287,6 +298,7 @@ public sealed class Tokenizer
"&&" => Symbol.And,
"||" => Symbol.Or,
"::" => Symbol.DoubleColon,
"x|" => Symbol.XOr,
_ => Symbol.None
},
1 => span[0] switch
@@ -361,9 +373,7 @@ public sealed class Tokenizer
}
}
return new IdentifierToken(
CreateSpan(lineStart, columnStart),
_content.Substring(start, _index - start));
return new IdentifierToken(CreateSpan(lineStart, columnStart), _content.Substring(start, _index - start));
}
private SourceSpan CreateSpan(int lineStart, int columnStart)