/// <summary> /// Parses an assignment or call command /// </summary> private ICommandNode ParseAssignmentOrCallCommand() { Debugger.Write("Parsing Assignment Command or Call Command"); Position startPosition = CurrentToken.Position; IdentifierNode identifier = ParseIdentifier(); if (CurrentToken.Type == TokenType.LeftBracket) { Debugger.Write("Parsing Call Command"); Accept(TokenType.LeftBracket); IParameterNode parameter = ParseParameter(); Accept(TokenType.RightBracket); return(new CallCommandNode(identifier, parameter)); } else if (CurrentToken.Type == TokenType.Becomes) { Debugger.Write("Parsing Assignment Command"); Accept(TokenType.Becomes); IExpressionNode expression = ParseExpression(); return(new AssignCommandNode(identifier, expression)); } else { return(new ErrorNode(startPosition)); } }
/** * C O M M A N D S */ /// <summary> /// Parses a skip command /// </summary> /// <returns>An abstract syntax tree representing the skip command</returns> private ICommandNode ParseSkipCommand() { Debugger.Write("Parsing Skip Command"); Position startPosition = CurrentToken.Position; return(new BlankCommandNode(startPosition)); }
/// <summary> /// Parses a for command /// </summary> private ICommandNode ParseForCommand() { Debugger.Write("Parsing For Command"); Position startPosition = CurrentToken.Position; Accept(TokenType.For); IdentifierNode identifier = ParseIdentifier(); // Declare I as a new variable of type integer with an undefined value VarDeclarationNode declaration = new VarDeclarationNode(identifier, new TypeDenoterNode( new IdentifierNode( new Token(TokenType.Identifier, "Integer", startPosition))), startPosition); // Evaluate E1 Accept(TokenType.Becomes); IExpressionNode becomesExpression = ParseExpression(); // Assign I to the value of E1 AssignCommandNode assign = new AssignCommandNode(identifier, becomesExpression); // Evaluate E2 Accept(TokenType.To); IExpressionNode toExpression = ParseExpression(); Accept(TokenType.Do); // Execute command ICommandNode command = ParseSingleCommand(); Accept(TokenType.Next); return(new ForCommandNode(declaration, assign, toExpression, command, startPosition)); }
/** * E X P R E S S I O N S */ /// <summary> /// Parses a value parameter /// </summary> private IParameterNode ParseValParameter() { Debugger.Write("Parsing Value Parameter"); IExpressionNode expression = ParseExpression(); return(new ExpressionParameterNode(expression)); }
/// <summary> /// Parses a single command /// </summary> private ICommandNode ParseSingleCommand() { Debugger.Write("Parsing single command"); switch (CurrentToken.Type) { case TokenType.Identifier: return(ParseAssignmentOrCallCommand()); case TokenType.If: return(ParseIfCommand()); case TokenType.While: return(ParseWhileCommand()); case TokenType.Let: return(ParseLetCommand()); case TokenType.Begin: return(ParseBeginCommand()); case TokenType.For: return(ParseForCommand()); default: return(ParseSkipCommand()); } }
/// <summary> /// Parses a type denoter /// </summary> private TypeDenoterNode ParseTypeDenoter() { Debugger.Write("Parsing Type Denoter"); IdentifierNode identifier = ParseIdentifier(); return(new TypeDenoterNode(identifier)); }
/// <summary> /// Parses an integer expression /// </summary> private IExpressionNode ParseIntExpression() { Debugger.Write("Parsing Int Expression"); IntegerLiteralNode intLit = ParseIntegerLiteral(); return(new IntegerExpressionNode(intLit)); }
/// <summary> /// Parses a primary expression /// </summary> private IExpressionNode ParsePrimaryExpression() { Debugger.Write("Parsing Primary Expression"); switch (CurrentToken.Type) { case TokenType.IntLiteral: return(ParseIntExpression()); case TokenType.CharLiteral: return(ParseCharExpression()); case TokenType.Identifier: return(ParseIdExpression()); case TokenType.Operator: return(ParseUnaryExpression()); case TokenType.LeftBracket: return(ParseBracketExpression()); default: Reporter.ReportError($"{CurrentToken.Position} -> Could not parse primary expression"); return(new ErrorNode(CurrentToken.Position)); } }
/// <summary> /// Parses a character expression /// </summary> private IExpressionNode ParseCharExpression() { Debugger.Write("Parsing Char Expression"); CharacterLiteralNode charLit = ParseCharacterLiteral(); return(new CharacterExpressionNode(charLit)); }
/// <summary> /// Parses a program /// </summary> private ProgramNode ParseProgram() { Debugger.Write($"Parsing program"); ICommandNode command = ParseCommand(); ProgramNode program = new ProgramNode(command); return(program); }
/// <summary> /// Parses a unary expresion /// </summary> private IExpressionNode ParseUnaryExpression() { Debugger.Write("Parsing Unary Expression"); OperatorNode operation = ParseOperator(); IExpressionNode expression = ParsePrimaryExpression(); return(new UnaryExpressionNode(operation, expression)); }
/** * L I T E R A L S */ /// <summary> /// Parses an integer literal /// </summary> private IntegerLiteralNode ParseIntegerLiteral() { Debugger.Write("Parsing integer literal"); Token integerLiteralToken = CurrentToken; Accept(TokenType.IntLiteral); return(new IntegerLiteralNode(integerLiteralToken)); }
/// <summary> /// Parses a character literal /// </summary> private CharacterLiteralNode ParseCharacterLiteral() { Debugger.Write("Parsing character literal"); Token characterLiteralToken = CurrentToken; Accept(TokenType.CharLiteral); return(new CharacterLiteralNode(characterLiteralToken)); }
/* * I D E N T I F I E R S */ /// <summary> /// Parses an identifier /// </summary> private IdentifierNode ParseIdentifier() { Debugger.Write("Parsing Identifier"); Token identifierToken = CurrentToken; Accept(TokenType.Identifier); return(new IdentifierNode(identifierToken)); }
/* * O P E R A T O R S */ /// <summary> /// Parses an operator /// </summary> private OperatorNode ParseOperator() { Debugger.Write("Parsing operator"); Token OperatorToken = CurrentToken; Accept(TokenType.Operator); return(new OperatorNode(OperatorToken)); }
/// <summary> /// Parses a bracket expression /// </summary> private IExpressionNode ParseBracketExpression() { Debugger.Write("Parsing Bracket Expression"); Accept(TokenType.LeftBracket); IExpressionNode expression = ParseExpression(); Accept(TokenType.RightBracket); return(expression); }
/// <summary> /// Parses a begin command /// </summary> private ICommandNode ParseBeginCommand() { Debugger.Write("Parsing Begin Command"); Accept(TokenType.Begin); ICommandNode command = ParseCommand(); Accept(TokenType.End); return(command); }
/// <summary> /// Parses a variable parameter /// </summary> private IParameterNode ParseVarParameter() { Debugger.Write("Parsing Variable Parameter"); Position startPosition = CurrentToken.Position; Accept(TokenType.Var); IdentifierNode identifier = ParseIdentifier(); return(new VarParameterNode(identifier, startPosition)); }
/// <summary> /// Parses a let command /// </summary> private ICommandNode ParseLetCommand() { Debugger.Write("Parsing Let Command"); Position startPosition = CurrentToken.Position; Accept(TokenType.Let); IDeclarationNode declaration = ParseDeclaration(); Accept(TokenType.In); ICommandNode command = ParseSingleCommand(); return(new LetCommandNode(declaration, command, startPosition)); }
/// <summary> /// Checks the current token is the expected kind and moves to the next token /// </summary> /// <param name="expectedType"></param> private void Accept(TokenType expectedType) { if (CurrentToken.Type == expectedType) { Debugger.Write($"Accepted {CurrentToken}"); MoveNext(); } else { Reporter.ReportError($"{CurrentToken.Position} -> " + $"Incorrect use of token type {CurrentToken.Type}"); } }
/// <summary> /// Parses a while command /// </summary> private WhileCommandNode ParseWhileCommand() { Debugger.Write("Parsing While Command"); Position startPosition = CurrentToken.Position; Accept(TokenType.While); IExpressionNode expression = ParseBracketExpression(); Accept(TokenType.Do); ICommandNode command = ParseSingleCommand(); return(new WhileCommandNode(expression, command, startPosition)); }
/// <summary> /// Parses a const declaration /// </summary> private IDeclarationNode ParseConstDeclaration() { Debugger.Write("Parsing Const Declaration"); Position startPosition = CurrentToken.Position; Accept(TokenType.Const); IdentifierNode identifier = ParseIdentifier(); Accept(TokenType.Is); IExpressionNode expression = ParseExpression(); return(new ConstDeclarationNode(identifier, expression, startPosition)); }
/// <summary> /// Parses a var declaration /// </summary> private IDeclarationNode ParseVarDeclaration() { Debugger.Write("Parsing Var Declaration"); Position startPosition = CurrentToken.Position; Accept(TokenType.Var); IdentifierNode identifier = ParseIdentifier(); Accept(TokenType.Colon); TypeDenoterNode typeDenoter = ParseTypeDenoter(); return(new VarDeclarationNode(identifier, typeDenoter, startPosition)); }
/// <summary> /// Parses an expression /// </summary> private IExpressionNode ParseExpression() { Debugger.Write("Parsing Expression"); IExpressionNode leftExpression = ParsePrimaryExpression(); while (CurrentToken.Type == TokenType.Operator) { OperatorNode operation = ParseOperator(); IExpressionNode rightExpression = ParsePrimaryExpression(); leftExpression = new BinaryExpressionNode(leftExpression, operation, rightExpression); } return(leftExpression); }
/// <summary> /// Parses a single declaration /// </summary> private IDeclarationNode ParseSingleDeclaration() { Debugger.Write("Parsing Single Declaration"); switch (CurrentToken.Type) { case TokenType.Const: return(ParseConstDeclaration()); case TokenType.Var: return(ParseVarDeclaration()); default: Reporter.ReportError($"{CurrentToken.Position} -> Could not parse single declaration"); return(new ErrorNode(CurrentToken.Position)); } }
/// <summary> /// Parses a command /// </summary> private ICommandNode ParseCommand() { Debugger.Write("Parsing command"); List <ICommandNode> commands = new List <ICommandNode>(); commands.Add(ParseSingleCommand()); while (CurrentToken.Type == TokenType.Semicolon) { Accept(TokenType.Semicolon); commands.Add(ParseSingleCommand()); } if (commands.Count == 1) { return(commands[0]); } else { return(new SequentialCommandNode(commands)); } }
/// <summary> /// Parses an if command /// </summary> private ICommandNode ParseIfCommand() { Debugger.Write("Parsing If Command"); Position startPosition = CurrentToken.Position; Accept(TokenType.If); IExpressionNode expression = ParseBracketExpression(); Accept(TokenType.Then); ICommandNode thenCommand = ParseSingleCommand(); if (CurrentToken.Type == TokenType.Else) { Accept(TokenType.Else); ICommandNode elseCommand = ParseSingleCommand(); Accept(TokenType.EndIf); return(new IfElseCommandNode(expression, thenCommand, elseCommand, startPosition)); } Accept(TokenType.EndIf); return(new IfCommandNode(expression, thenCommand, startPosition)); }
/** * D E C L A R A T I O N S */ /// <summary> /// Parses a declaration /// </summary> private IDeclarationNode ParseDeclaration() { Debugger.Write("Parsing Declaration"); List <IDeclarationNode> declarations = new List <IDeclarationNode>(); declarations.Add(ParseSingleDeclaration()); while (CurrentToken.Type == TokenType.Semicolon) { Accept(TokenType.Semicolon); declarations.Add(ParseSingleDeclaration()); } if (declarations.Count == 1) { return(declarations[0]); } else { return(new SequentialDeclarationNode(declarations)); } }
/// <summary> /// Parses ID Expression /// </summary> private IExpressionNode ParseIdExpression() { Debugger.Write("Parsing Call Expression or Identifier Expression"); Position startPosition = CurrentToken.Position; IdentifierNode identifier = ParseIdentifier(); if (CurrentToken.Type == TokenType.LeftBracket) { // Parse call expression Debugger.Write("Parsing Call Expression"); Accept(TokenType.LeftBracket); IParameterNode parameter = ParseParameter(); Accept(TokenType.RightBracket); return(new CallExpressionNode(identifier, parameter)); } else { Debugger.Write("Parsing Identifier Expression"); return(new IdExpressionNode(identifier)); } }
/** * P A R A M E T E R S */ /// <summary> /// Parses a parameter /// </summary> private IParameterNode ParseParameter() { Debugger.Write("Parsing Parameter"); switch (CurrentToken.Type) { case TokenType.Identifier: case TokenType.IntLiteral: case TokenType.CharLiteral: case TokenType.Operator: case TokenType.LeftBracket: return(ParseValParameter()); case TokenType.Var: return(ParseVarParameter()); case TokenType.RightBracket: return(new BlankParameterNode(CurrentToken.Position)); default: return(new ErrorNode(CurrentToken.Position)); } }