object Evaluate(Expression expression) { if (expression is BinaryOperator) { var binOp = (BinaryOperator)expression; TypeBinding binding = TypeBindings.DecideType(binOp.LeftOperand, symbolTable, errors); return TypeModels.EvaluateBinaryOperator(binding, binOp.Oper.Lexeme, Evaluate (binOp.LeftOperand), Evaluate(binOp.RightOperand)); } else if (expression is UnaryOperator) { var unOp = (UnaryOperator)expression; TypeBinding binding = TypeBindings.DecideType(unOp.Operand, symbolTable, errors); return TypeModels.EvaluateUnaryOperator(binding, unOp.Oper.Lexeme, Evaluate (unOp.Operand)); } else if (expression is ExpressionLeaf) { var leaf = (ExpressionLeaf)expression; switch(leaf.Token.Category) { case Category.Literal_Integer: return int.Parse(leaf.Token.Lexeme); break; case Category.Literal_String: return leaf.Token.Lexeme; break; case Category.Identifier: if (symbolTable.IsDeclared (leaf.Token)) { return symbolTable.GetValue(leaf.Token); } else { //should be handled by semantic analyser throw new InvalidOperationException("Undeclared variable"); } break; default: return null; } } throw new InvalidOperationException("Unrecognized expression class"); }
public static TypeBinding DecideType(Expression expression, SymbolTable symbolTable, ErrorContainer errors) { if (expression is BinaryOperator) { var binOp = (BinaryOperator)expression; TypeBinding leftType = DecideType (binOp.LeftOperand, symbolTable, errors); TypeBinding rightType = DecideType (binOp.RightOperand, symbolTable, errors); if(leftType == null || rightType == null) { return null; } if (leftType != rightType) { errors.AddError (binOp.Oper, ErrorType.SemanticError, "Types of left and right operand do not match"); return null; } var ret = rightType.Operate (binOp.Oper.Lexeme); if(ret == null) { errors.AddError (binOp.Oper, ErrorType.SemanticError, "Could not apply operator to given types"); } return ret; } else if (expression is UnaryOperator) { var unOp = (UnaryOperator)expression; TypeBinding operandType = DecideType (unOp.Operand, symbolTable, errors); if (operandType == null) { return null; } var ret = operandType.Operate (unOp.Oper.Lexeme); if(ret == null) { errors.AddError(unOp.Oper, ErrorType.SemanticError, "Could not apply operator to given type"); } return ret; } else if (expression is ExpressionLeaf) { var leaf = (ExpressionLeaf)expression; switch(leaf.Token.Category) { case Category.Literal_Integer: return GetTypeByName(PRIMITIVE_INTEGER_NAME); case Category.Literal_String: return GetTypeByName(PRIMITIVE_STRING_NAME); case Category.Identifier: if (symbolTable.IsDeclared (leaf.Token)) { return TypeBindings.GetTypeByName(symbolTable.GetVariableType(leaf.Token)); } else { errors.AddError (leaf.Token, ErrorType.SemanticError, "Undeclared variable"); return null; } } return null; } return null; }
void DoTypeChecking(Expression expression, string type) { /*if (TypeSystem.GetCategoryFromType (decideType (expression)) != type) { errors.addError(expression.head(), ErrorType.Semantic_Error, "Expression does not match the required type"); }*/ var binding = TypeBindings.DecideType (expression, symbolTable, errors); if (binding == null) { //expression was inconsistent return; } else if (binding.Name != type) { errors.AddError(expression.Head(), ErrorType.SemanticError, "Expression does not match the required type"); } }
//checks that given expression is consistent, namely that types of each left and right operand match void DoConsistencyChecking(Expression expression) { TypeBindings.DecideType(expression, symbolTable, errors); }
void AssertionMessage(int line, int column, Expression e) { string s = "Assertion near line " + line; s = s + " column " + column + " failed. Assertion \"" + e.ToString() + "\" was false."; Console.WriteLine(s); }