...
This commit is contained in:
@@ -120,10 +120,65 @@ public sealed class Parser(List<Token> tokens)
|
||||
throw new Exception("Not a valid followup for expression statement");
|
||||
}
|
||||
|
||||
private NodeExpression ParseExpression()
|
||||
private NodeExpression ParseExpression(int minPrecedence = -1)
|
||||
{
|
||||
var startIndex = index;
|
||||
|
||||
var left = ParseExpressionLeaf();
|
||||
|
||||
while (TryPeekBinaryOperator(out var op) && GetPrecedence(op) >= minPrecedence)
|
||||
{
|
||||
Consume();
|
||||
var right = ParseExpression(GetPrecedence(op) + 1);
|
||||
left = new NodeExpressionBinary(TokensFrom(startIndex), left, op, right);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
private static int GetPrecedence(NodeExpressionBinary.Op operation)
|
||||
{
|
||||
return operation switch
|
||||
{
|
||||
NodeExpressionBinary.Op.Multiply => 10,
|
||||
NodeExpressionBinary.Op.Divide => 10,
|
||||
NodeExpressionBinary.Op.Modulo => 10,
|
||||
|
||||
NodeExpressionBinary.Op.Add => 9,
|
||||
NodeExpressionBinary.Op.Subtract => 9,
|
||||
|
||||
NodeExpressionBinary.Op.LeftShift => 8,
|
||||
NodeExpressionBinary.Op.RightShift => 8,
|
||||
|
||||
NodeExpressionBinary.Op.GreaterThan => 7,
|
||||
NodeExpressionBinary.Op.GreaterThanOrEqual => 7,
|
||||
NodeExpressionBinary.Op.LessThan => 7,
|
||||
NodeExpressionBinary.Op.LessThanOrEqual => 7,
|
||||
|
||||
NodeExpressionBinary.Op.Equal => 7,
|
||||
NodeExpressionBinary.Op.NotEqual => 7,
|
||||
|
||||
// NodeExpressionBinary.Op.BitwiseAnd => 6,
|
||||
// NodeExpressionBinary.Op.BitwiseXor => 5,
|
||||
// NodeExpressionBinary.Op.BitwiseOr => 4,
|
||||
|
||||
NodeExpressionBinary.Op.LogicalAnd => 3,
|
||||
NodeExpressionBinary.Op.LogicalOr => 2,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(operation), operation, null)
|
||||
};
|
||||
}
|
||||
|
||||
private NodeExpression ParseExpressionLeaf()
|
||||
{
|
||||
var startIndex = index;
|
||||
|
||||
if (TryExpectSymbol(Symbol.OpenParen))
|
||||
{
|
||||
var value = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseParen);
|
||||
return value;
|
||||
}
|
||||
|
||||
if (TryExpectIntLiteral(out var intLiteral))
|
||||
{
|
||||
return new NodeExpressionIntLiteral(TokensFrom(startIndex), intLiteral);
|
||||
@@ -144,7 +199,7 @@ public sealed class Parser(List<Token> tokens)
|
||||
return new NodeExpressionIdent(TokensFrom(startIndex), ident);
|
||||
}
|
||||
|
||||
throw new Exception("Not a valid expression");
|
||||
throw new Exception("Not a valid expression leaf");
|
||||
}
|
||||
|
||||
private NodeType ParseType()
|
||||
@@ -323,6 +378,67 @@ public sealed class Parser(List<Token> tokens)
|
||||
|
||||
return tokens[index + offset];
|
||||
}
|
||||
|
||||
private bool TryPeekBinaryOperator(out NodeExpressionBinary.Op op)
|
||||
{
|
||||
if (Peek() is not TokenSymbol token)
|
||||
{
|
||||
op = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (token.Symbol)
|
||||
{
|
||||
case Symbol.Plus:
|
||||
op = NodeExpressionBinary.Op.Add;
|
||||
return true;
|
||||
case Symbol.Minus:
|
||||
op = NodeExpressionBinary.Op.Subtract;
|
||||
return true;
|
||||
case Symbol.Star:
|
||||
op = NodeExpressionBinary.Op.Multiply;
|
||||
return true;
|
||||
case Symbol.ForwardSlash:
|
||||
op = NodeExpressionBinary.Op.Divide;
|
||||
return true;
|
||||
case Symbol.Percent:
|
||||
op = NodeExpressionBinary.Op.Modulo;
|
||||
return true;
|
||||
case Symbol.BangEqual:
|
||||
op = NodeExpressionBinary.Op.NotEqual;
|
||||
return true;
|
||||
case Symbol.EqualEqual:
|
||||
op = NodeExpressionBinary.Op.Equal;
|
||||
return true;
|
||||
case Symbol.LessThan:
|
||||
op = NodeExpressionBinary.Op.LessThan;
|
||||
return true;
|
||||
case Symbol.LessThanEqual:
|
||||
op = NodeExpressionBinary.Op.LessThanOrEqual;
|
||||
return true;
|
||||
case Symbol.GreaterThan:
|
||||
op = NodeExpressionBinary.Op.GreaterThan;
|
||||
return true;
|
||||
case Symbol.GreaterThanEqual:
|
||||
op = NodeExpressionBinary.Op.GreaterThanOrEqual;
|
||||
return true;
|
||||
case Symbol.LessThanLessThan:
|
||||
op = NodeExpressionBinary.Op.LeftShift;
|
||||
return true;
|
||||
case Symbol.GreaterThanGreaterThan:
|
||||
op = NodeExpressionBinary.Op.RightShift;
|
||||
return true;
|
||||
case Symbol.AmpersandAmpersand:
|
||||
op = NodeExpressionBinary.Op.LogicalAnd;
|
||||
return true;
|
||||
case Symbol.PipePipe:
|
||||
op = NodeExpressionBinary.Op.LogicalOr;
|
||||
return true;
|
||||
default:
|
||||
op = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Node(List<Token> tokens)
|
||||
@@ -359,32 +475,32 @@ public sealed class NodeStatementFuncCall(List<Token> tokens, NodeExpression tar
|
||||
public readonly List<NodeExpression> Parameters = parameters;
|
||||
}
|
||||
|
||||
internal class NodeStatementReturn(List<Token> tokens, NodeExpression value) : NodeStatement(tokens)
|
||||
public class NodeStatementReturn(List<Token> tokens, NodeExpression value) : NodeStatement(tokens)
|
||||
{
|
||||
public readonly NodeExpression Value = value;
|
||||
}
|
||||
|
||||
internal class NodeStatementVariableDeclaration(List<Token> tokens, TokenIdent name, NodeType type, NodeExpression value) : NodeStatement(tokens)
|
||||
public class NodeStatementVariableDeclaration(List<Token> tokens, TokenIdent name, NodeType type, NodeExpression value) : NodeStatement(tokens)
|
||||
{
|
||||
public readonly TokenIdent Name = name;
|
||||
public readonly NodeType Type = type;
|
||||
public readonly NodeExpression Value = value;
|
||||
}
|
||||
|
||||
internal class NodeStatementAssignment(List<Token> tokens, NodeExpression target, NodeExpression value) : NodeStatement(tokens)
|
||||
public class NodeStatementAssignment(List<Token> tokens, NodeExpression target, NodeExpression value) : NodeStatement(tokens)
|
||||
{
|
||||
public readonly NodeExpression Target = target;
|
||||
public readonly NodeExpression Value = value;
|
||||
}
|
||||
|
||||
internal class NodeStatementIf(List<Token> tokens, NodeExpression condition, NodeStatement thenBlock, NodeStatement? elseBlock) : NodeStatement(tokens)
|
||||
public class NodeStatementIf(List<Token> tokens, NodeExpression condition, NodeStatement thenBlock, NodeStatement? elseBlock) : NodeStatement(tokens)
|
||||
{
|
||||
public readonly NodeExpression Condition = condition;
|
||||
public readonly NodeStatement ThenBlock = thenBlock;
|
||||
public readonly NodeStatement? ElseBlock = elseBlock;
|
||||
}
|
||||
|
||||
internal class NodeStatementWhile(List<Token> tokens, NodeExpression condition, NodeStatement block) : NodeStatement(tokens)
|
||||
public class NodeStatementWhile(List<Token> tokens, NodeExpression condition, NodeStatement block) : NodeStatement(tokens)
|
||||
{
|
||||
public readonly NodeExpression Condition = condition;
|
||||
public readonly NodeStatement Block = block;
|
||||
@@ -412,6 +528,40 @@ public sealed class NodeExpressionIdent(List<Token> tokens, TokenIdent value) :
|
||||
public readonly TokenIdent Value = value;
|
||||
}
|
||||
|
||||
public class NodeExpressionBinary(List<Token> tokens, NodeExpression left, NodeExpressionBinary.Op operation, NodeExpression right) : NodeExpression(tokens)
|
||||
{
|
||||
public NodeExpression Left { get; } = left;
|
||||
public readonly Op Operation = operation;
|
||||
public NodeExpression Right { get; } = right;
|
||||
|
||||
|
||||
public enum Op
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Modulo,
|
||||
|
||||
Equal,
|
||||
NotEqual,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual,
|
||||
|
||||
LeftShift,
|
||||
RightShift,
|
||||
|
||||
// BitwiseAnd,
|
||||
// BitwiseXor,
|
||||
// BitwiseOr,
|
||||
|
||||
LogicalAnd,
|
||||
LogicalOr,
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class NodeType(List<Token> tokens) : Node(tokens);
|
||||
|
||||
public sealed class NodeTypeVoid(List<Token> tokens) : NodeType(tokens);
|
||||
|
||||
Reference in New Issue
Block a user