ShintenScript/Parser.cs

147 lines
4.0 KiB
C#
Raw Normal View History

2023-02-02 14:05:53 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShintenScript
{
public class Parser
{
protected readonly Lexer lexer;
public Parser(Lexer lexer)
{
this.lexer = lexer;
}
public IASTNode ParseExpression()
{
if (lexer.Accept(Token.Type.SEMICOLON))
{
lexer.Pop();
return new ASTNodeLiteral(null);
}
return ParseExpressionAssignLevel();
}
public IASTNode ParseExpressionAssignLevel()
{
IASTNode lhs = ParseExpressionComparisonLevel();
return lhs;
}
public IASTNode ParseExpressionComparisonLevel()
{
List<IASTNode> nodes = new List<IASTNode>();
List<Token.Type> comparisons = new List<Token.Type>();
nodes.Add(ParseExpressionAdditiveLevel());
while (lexer.Accept(Token.Type.EQ, Token.Type.NE, Token.Type.LT, Token.Type.GT, Token.Type.LE, Token.Type.GE))
{
comparisons.Add(lexer.Pop().type);
nodes.Add(ParseExpressionAdditiveLevel());
}
if (nodes.Count == 1)
return nodes[0];
return new ASTNodeComparison(nodes, comparisons);
}
public IASTNode ParseExpressionAdditiveLevel()
{
IASTNode lhs = ParseExpressionMultiplicativeLevel();
if (lexer.Accept(Token.Type.PLUS, Token.Type.MINUS))
{
bool isAddition = lexer.Pop().type == Token.Type.PLUS;
IASTNode rhs = ParseExpressionAdditiveLevel();
if (isAddition)
return new ASTNodeAdd(lhs, rhs);
else
return new ASTNodeSubtract(lhs, rhs);
}
return lhs;
}
public IASTNode ParseExpressionMultiplicativeLevel()
{
IASTNode lhs = ParseExpressionWithPrefix();
if (lexer.Accept(Token.Type.ASTERISK, Token.Type.SLASH))
{
bool isMultiplication = lexer.Pop().type == Token.Type.ASTERISK;
IASTNode rhs = ParseExpressionMultiplicativeLevel();
if (isMultiplication)
return new ASTNodeMultiply(lhs, rhs);
else
return new ASTNodeDivide(lhs, rhs);
}
return lhs;
}
public IASTNode ParseExpressionWithPrefix()
{
if (lexer.Accept(Token.Type.PLUS))
lexer.Pop();
if (lexer.Accept(Token.Type.MINUS))
{
lexer.Pop();
return new ASTNodeNegative(ParseExpressionPrimary());
}
return ParseExpressionPrimary();
}
public IASTNode ParseExpressionPrimary()
{
if (lexer.Accept(Token.Type.NUMBER))
return new ASTNodeLiteral(lexer.Pop().data);
if (lexer.Accept(Token.Type.LPAREN))
return ParseExpressionParenthesised();
if (lexer.Accept(Token.Type.LBRACE))
return ParseBlock();
throw new ParsingException("Expected expression");
}
public IASTNode ParseExpressionParenthesised()
{
lexer.Expect(Token.Type.LPAREN);
IASTNode expression = ParseExpression();
lexer.Expect(Token.Type.RPAREN);
return expression;
}
public IASTNode ParseBlock()
{
lexer.Expect(Token.Type.LBRACE);
List<IASTNode> statements = new List<IASTNode>();
while (!lexer.Accept(Token.Type.RBRACE))
{
statements.Add(ParseExpression());
}
lexer.Pop();
if (statements.Count == 0)
return new ASTNodeLiteral(null);
return new ASTNodeBlock(statements);
}
}
}