public LiteralValueNode ParseLitealValue(Token token) { if (token.Type == TokenType.LiteralValue) { LiteralValueNode value = null; CobaltType cobaltType = token.GetData <CobaltType>(TokenDataKeys.COBALT_TYPE); switch (cobaltType) { case CobaltType.Boolean: value = new BooleanValueNode(token.SourceLine, token.GetData <bool>(TokenDataKeys.LITERAL_VALUE)); break; case CobaltType.Float: value = new FloatValueNode(token.SourceLine, token.GetData <float>(TokenDataKeys.LITERAL_VALUE)); break; case CobaltType.Integer: value = new IntegerValueNode(token.SourceLine, token.GetData <int>(TokenDataKeys.LITERAL_VALUE)); break; default: throw new CompilerException($"`{MethodBase.GetCurrentMethod().Name}` called with unknown Cobalt type `{cobaltType}`."); } return(value); } else { throw new CompilerException($"`{MethodBase.GetCurrentMethod().Name}` called with a bad token. Expected a token of type `{TokenType.LiteralValue}`, got token of type `{token.Type}` instead."); } }
public void ShouldParseTypeKeywords(CobaltType type) { // Arrange Token token = new Token(TokenType.TypeKeyword, 1, 0); token.SetData(TokenDataKeys.COBALT_TYPE, type); // Act TypeKeywordNode node = Parser.ParseTypeKeyword(token); // Assert switch (type) { case CobaltType.Boolean: Assert.True(node is BooleanTypeKeywordNode); break; case CobaltType.Float: Assert.True(node is FloatTypeKeywordNode); break; case CobaltType.Integer: Assert.True(node is IntegerTypeKeywordNode); break; default: throw new XunitException("No test implemented for this type."); } Assert.Equal(type, node.Type); }
public TypeKeywordNode ParseTypeKeyword(Token token) { if (token.Type == TokenType.TypeKeyword) { TypeKeywordNode type = null; CobaltType cobaltType = token.GetData <CobaltType>(TokenDataKeys.COBALT_TYPE); switch (cobaltType) { case CobaltType.Boolean: type = new BooleanTypeKeywordNode(token.SourceLine); break; case CobaltType.Float: type = new FloatTypeKeywordNode(token.SourceLine); break; case CobaltType.Integer: type = new IntegerTypeKeywordNode(token.SourceLine); break; default: throw new CompilerException($"`{MethodBase.GetCurrentMethod().Name}` called with unknown Cobalt type `{cobaltType}`."); } return(type); } else { throw new CompilerException($"`{MethodBase.GetCurrentMethod().Name}` called with a bad token. Expected a token of type `{TokenType.TypeKeyword}`, got token of type `{token.Type}` instead."); } }
private void AnalyzeVariableDeclaration(VariableDeclarationStatementNode variableDeclaration) { CobaltType variableType; if (variableDeclaration.TypeKeyword != null && variableDeclaration.Expression != null) { CobaltType expressionType = AnalyzeExpression(variableDeclaration.Expression); if (expressionType != variableDeclaration.TypeKeyword.Type) { throw new CobaltTypeError($"Type mismatch between explicitely declared type of variable `{variableDeclaration.Identifier.IdentifierName}` ({variableDeclaration.TypeKeyword.Type}) and type of expression ({expressionType}).", variableDeclaration.Expression.SourceLine); } variableType = expressionType; } else if (variableDeclaration.TypeKeyword == null && variableDeclaration.Expression != null) { variableType = AnalyzeExpression(variableDeclaration.Expression); } else if (variableDeclaration.TypeKeyword != null && variableDeclaration.Expression == null) { variableType = variableDeclaration.TypeKeyword.Type; } else { throw new CompilerException($"`{MethodBase.GetCurrentMethod().Name}` called with bad AST stucture in variable declaration from line {variableDeclaration.SourceLine}."); } Symbol variable = new Symbol(variableDeclaration.Identifier.IdentifierName, new VariableTypeSignature(variableType), variableDeclaration.Expression != null, variableDeclaration.SourceLine); variableDeclaration.Parent.RegisterSymbol(variable); }
/// <summary> /// Creates a token for a type keyword. /// </summary> /// <param name="type">The Cobalt type this is a keyword for.</param> /// <param name="line">The line in the source code where the token is from.</param> /// <param name="positionOnLine">The position on the source code line.</param> /// <returns>Returns the newly created token.</returns> private Token CreateTypeKeywordToken(CobaltType type, int line, int positionOnLine) { Token token = new Token(TokenType.TypeKeyword, line, positionOnLine); token.SetData(TokenDataKeys.COBALT_TYPE, type); return(token); }
/// <summary> /// Creates a token for a literal value. /// </summary> /// <param name="type">The Cobalt type of the literal vbalue.</param> /// <param name="value">The literal value.</param> /// <param name="line">The line in the source code where the token is from.</param> /// <param name="positionOnLine">The position on the source code line.</param> /// <returns>Returns the newly created token.</returns> private Token CreateLiteralValueToken(CobaltType type, object value, int line, int positionOnLine) { Token token = new Token(TokenType.LiteralValue, line, positionOnLine); token.SetData(TokenDataKeys.COBALT_TYPE, type); token.SetData(TokenDataKeys.LITERAL_VALUE, value); return(token); }
public void ShouldParseLiteralValues(object value, CobaltType type) { // Arrange Token token = new Token(TokenType.LiteralValue, 1, 0); token.SetData(TokenDataKeys.LITERAL_VALUE, value); token.SetData(TokenDataKeys.COBALT_TYPE, type); // Act LiteralValueNode node = Parser.ParseLitealValue(token); // Assert switch (type) { case CobaltType.Boolean: if (node is BooleanValueNode booleanValue) { Assert.Equal((bool)value, booleanValue.Value); } else { throw new XunitException("Wrong Cobalt type."); } break; case CobaltType.Float: if (node is FloatValueNode floatValue) { Assert.Equal((float)value, floatValue.Value); } else { throw new XunitException("Wrong Cobalt type."); } break; case CobaltType.Integer: if (node is IntegerValueNode integerValue) { Assert.Equal((int)value, integerValue.Value); } else { throw new XunitException("Wrong Cobalt type."); } break; default: throw new XunitException("No test implemented for this type."); } }
public void ShouldParseSingleValueExpressions(object value, CobaltType type) { // Arrange List <Token> tokens = new List <Token>() { new Token(TokenType.LiteralValue, 1, 0) }; tokens.First().SetData(TokenDataKeys.LITERAL_VALUE, value); tokens.First().SetData(TokenDataKeys.COBALT_TYPE, type); // Act ExpressionNode expression = Parser.ParseExpression(tokens); // Assert if (expression is SingleLeafExpressionNode singleLeafExpression) { Assert.Equal(expression, singleLeafExpression.Leaf.Parent); if (singleLeafExpression.Leaf is BooleanValueNode booleanValue) { Assert.Equal(CobaltType.Boolean, type); Assert.Equal((bool)value, booleanValue.Value); } else if (singleLeafExpression.Leaf is FloatValueNode floatValue) { Assert.Equal(CobaltType.Float, type); Assert.Equal((float)value, floatValue.Value); } else if (singleLeafExpression.Leaf is IntegerValueNode integerValue) { Assert.Equal(CobaltType.Integer, type); Assert.Equal((int)value, integerValue.Value); } else { throw new XunitException("Wrong expression type."); } } else { throw new XunitException("Wrong expression type."); } }
private void AnalyzeVariableAssignment(VariableAssignmentStatementNode variableAssignment) { Symbol variable = variableAssignment.Parent.LookupSymbol(variableAssignment.Identifier.IdentifierName); CobaltType expressionType = AnalyzeExpression(variableAssignment.Expression); if (variable.Type is VariableTypeSignature variableType) { if (variableType.CobaltType == expressionType) { variable.Initialized = true; } else { throw new CobaltTypeError($"Type mismatch between variable type of variable `{variableAssignment.Identifier.IdentifierName}` ({variableType.CobaltType}) and type of expression ({expressionType}).", variableAssignment.Expression.SourceLine); } } else { throw new CompilerException($"The type signature of identifier `{variable.Identifier}` is not a variable type signature."); } }
public LiteralValueNode(int sourceLine, CobaltType type) : base(sourceLine) { Type = type; }
public VariableTypeSignature(CobaltType type) { CobaltType = type; }
public TypeKeywordNode(int sourceLine, CobaltType type) : base(sourceLine) { Type = type; }
private bool IsNumberType(CobaltType type) { return(type == CobaltType.Integer || type == CobaltType.Float); }
public void ShouldParseOutputStatementWithSingleValue(object value, CobaltType type) { // Arrange List <Token> tokens = new List <Token>() { new Token(TokenType.StandardOutput, 0, 0), new Token(TokenType.LiteralValue, 0, 0), new Token(TokenType.Semicolon, 0, 0), }; tokens.ElementAt(1).SetData(TokenDataKeys.LITERAL_VALUE, value); tokens.ElementAt(1).SetData(TokenDataKeys.COBALT_TYPE, type); // Act CobaltProgram program = Parser.Parse(tokens); // Assert Assert.Single(program.Code.Statements); StatementNode statement = program.Code.Statements.First(); if (statement is StandardOutputStatementNode outputStatement) { Assert.Equal(program.Code, outputStatement.Parent); ExpressionNode expression = outputStatement.Expression; if (expression is SingleLeafExpressionNode singleLeafExpression) { switch (type) { case CobaltType.Boolean: if (singleLeafExpression.Leaf is BooleanValueNode booleanValue) { Assert.Equal((bool)value, booleanValue.Value); } else { throw new XunitException("Wrong Cobalt type."); } break; case CobaltType.Float: if (singleLeafExpression.Leaf is FloatValueNode floatValue) { Assert.Equal((float)value, floatValue.Value); } else { throw new XunitException("Wrong Cobalt type."); } break; case CobaltType.Integer: if (singleLeafExpression.Leaf is IntegerValueNode integerValue) { Assert.Equal((int)value, integerValue.Value); } else { throw new XunitException("Wrong Cobalt type."); } break; default: throw new XunitException("No test implemented for this type!"); } } else { throw new XunitException("Wrong expression type."); } } else { throw new XunitException("Wrong node type."); } }