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 nodes = new List(); List comparisons = new List(); 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 statements = new List(); while (!lexer.Accept(Token.Type.RBRACE)) { statements.Add(ParseExpression()); } lexer.Pop(); if (statements.Count == 0) return new ASTNodeLiteral(null); return new ASTNodeBlock(statements); } } }