public override bool Validate(SymbolTableLight table) { SymbolTableLight tableInternal = null; bool ok = true; foreach (IfClause clause in Clauses) { tableInternal = new SymbolTableLight(table); bool validExpr = clause.Condition.Validate(tableInternal); ok = ok && validExpr; if (validExpr && clause.Condition.ResultType.TypeEnum != VariableTypeEnum.Bool) { CompilerServices.AddError( clause.Condition.Location, "Expression in if statement must be type of bool" ); ok = false; } bool validStatements = CompilerServices.ValidateStatementList(clause.Statements, tableInternal); ok = ok && validStatements; } if (AlternativeStatements != null) { tableInternal = new SymbolTableLight(table); bool validAlternative = CompilerServices.ValidateStatementList(AlternativeStatements, tableInternal); ok = ok && validAlternative; } return ok; }
public override bool Validate(SymbolTableLight table) { SymbolTableLight tableInternal = new SymbolTableLight(table); bool valid = Condition.Validate(tableInternal); if (valid && Condition.ResultType.TypeEnum != VariableTypeEnum.Bool) { CompilerServices.AddError( Condition.Location, "DoWhile cycle condition must be type of bool!" ); return false; } bool validBody = CompilerServices.ValidateStatementList(Statements, tableInternal); valid = valid && validBody; return valid; }
/// <summary> /// Semanthic analize /// </summary> /// <returns>Everything was correct?</returns> public abstract bool Validate(SymbolTableLight table);
public override bool Validate(L1Specializer.Metadata.SymbolTableLight table) { if (DeclareVariable != String.Empty) { if (VariableType.TypeEnum != VariableTypeEnum.Integer && VariableType.TypeEnum != VariableTypeEnum.Char) { CompilerServices.AddError( Location, "Cycle variable must be type of int or char!" ); return false; } if (table.TryGetSymbol(DeclareVariable) != null) { CompilerServices.AddError( Location, "Declared cycle variable already exists!" ); return false; } bool valid = Init.Validate(table); if (valid) { if (!CompilerServices.IsAssignable(VariableType, Init.ResultType)) { CompilerServices.AddError( Location, "Cycle variable initialization expression has different type!" ); return false; } } else return false; } else { if (Init.LeftNode.LeafType != ExpressionLeafType.VariableAccess) { CompilerServices.AddError( Location, "Error in cycle definition: no variable reference presented!" ); return false; } bool valid = Init.Validate(table); if (!valid) return false; } bool validStep = Step.Validate(table); bool validEnd = EndValue.Validate(table); if (validEnd && validStep) { if (Step.ResultType.TypeEnum != VariableTypeEnum.Integer) { CompilerServices.AddError( Location, "Cycle step must be type of int!" ); return false; } if (EndValue.ResultType.TypeEnum != VariableTypeEnum.Integer && EndValue.ResultType.TypeEnum != VariableTypeEnum.Char) { CompilerServices.AddError( Location, "Cycle end value must be type of int or char!" ); return false; } } else return false; SymbolTableLight newTable = new SymbolTableLight(table); if (DeclareVariable != String.Empty) { newTable.AddSymbol(new SymbolLight(DeclareVariable, VariableType)); } bool res = CompilerServices.ValidateStatementList(Statements, newTable); return res; }
public override bool Validate(SymbolTableLight table) { if (IsLeaf) { #region Leaf nodes if (LeafType == ExpressionLeafType.Constant) { return true; } else if (LeafType == ExpressionLeafType.ArrayAlloc) { bool valid = LeftNode.Validate(table); if (valid) { if (LeftNode.ResultType.TypeEnum != VariableTypeEnum.Integer) { valid = false; CompilerServices.AddError( LeftNode.Location, "Array size must be type of int!" ); } } return valid; } else if (LeafType == ExpressionLeafType.VariableAccess) { SymbolLight symbol = table.TryGetSymbol((string)Value); if (symbol != null) { ResultType = symbol.Type; ResultType.IsReadonly = symbol.IsReadonly; return true; } else { CompilerServices.AddError( Location, "Unknown variable!" ); return false; } } else if (LeafType == ExpressionLeafType.FunctionCall) { VAList args = VAList; string name = (string)Value; LexLocation location = Location; VariableType returnType = null; bool valid = CompilerServices.ValidateFunctionCall(name, args, table, location, ref returnType); ResultType = returnType; return valid; } else if (LeafType == ExpressionLeafType.ArrayLength) { ResultType = VariableType.IntType; bool valid = LeftNode.Validate(table); if (valid) { if (LeftNode.ResultType.TypeEnum != VariableTypeEnum.Array) { CompilerServices.AddError( LeftNode.Location, "ArrayLength argument must be type of array!" ); return false; } } return valid; } #endregion return false; } else { #region Not leaf nodes if (OpType == OperationType.ArrayAccess) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (validLeft && validRight) { if (LeftNode.ResultType.TypeEnum != VariableTypeEnum.Array) { CompilerServices.AddError( Location, "Not array variable used as array!" ); return false; } ResultType = LeftNode.ResultType.NestedType; if (RightNode.ResultType.TypeEnum != VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum != VariableTypeEnum.Char) { CompilerServices.AddError( LeftNode.Location, "Array index must be type of int!" ); return false; } return true; } return false; } else if (OpType == OperationType.Assign) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if ((LeftNode.LeafType != ExpressionLeafType.VariableAccess) && (LeftNode.OpType != OperationType.ArrayAccess)) { CompilerServices.AddError( LeftNode.Location, "Left part of assign expression must be local variable, function parameter or array element!" ); return false; } if (LeftNode.ResultType.IsReadonly) { CompilerServices.AddError( LeftNode.Location, "This variable can't be changed after initialization!" ); return false; } if (!CompilerServices.IsAssignable(LeftNode.ResultType, RightNode.ResultType)) { CompilerServices.AddError( Location, "Assign opertion impossible bacause of operators type difference!" ); return false; } ResultType = LeftNode.ResultType; return true; } else if (OpType == OperationType.Plus) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.IntType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.CharType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.CharType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion +" ); return false; } else if (OpType == OperationType.Minus) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.IntType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.IntType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.CharType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion -" ); return false; } else if (OpType == OperationType.UMinus) { bool validLeft = LeftNode.Validate(table); if (!validLeft) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.IntType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.IntType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion unary -" ); return false; } else if (OpType == OperationType.UNot) { bool validLeft = LeftNode.Validate(table); if (!validLeft) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Bool) { ResultType = VariableType.BoolType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion unary not" ); return false; } else if (OpType == OperationType.Power || OpType == OperationType.Mult || OpType == OperationType.Div || OpType == OperationType.Mod) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.IntType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion " + OpType ); return false; } else if (OpType == OperationType.And || OpType == OperationType.Or || OpType == OperationType.Xor) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Bool && RightNode.ResultType.TypeEnum == VariableTypeEnum.Bool) { ResultType = VariableType.BoolType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion " + OpType ); return false; } else if (OpType == OperationType.Gr || OpType == OperationType.Le || OpType == OperationType.Greq || OpType == OperationType.Leeq) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.BoolType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion " + OpType ); return false; } else if (OpType == OperationType.Equals || OpType == OperationType.NotEquals) { bool validLeft = LeftNode.Validate(table); bool validRight = RightNode.Validate(table); if (!validLeft || !validRight) { return false; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Integer && RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Integer) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char && RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Bool && RightNode.ResultType.TypeEnum == VariableTypeEnum.Bool) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Array && RightNode.ResultType.TypeEnum == VariableTypeEnum.Array) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.Array && RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { ResultType = VariableType.BoolType; return true; } if (LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL && RightNode.ResultType.TypeEnum == VariableTypeEnum.Array) { ResultType = VariableType.BoolType; return true; } CompilerServices.AddError( Location, "Bad types in opertaion " + OpType ); return false; } #endregion return false; } }
public SymbolTableLight(SymbolTableLight parent) { f_symbols = new List<SymbolLight>(parent.f_symbols); }
public static bool ValidateStatementList(StatementList statements, SymbolTableLight table) { bool ok = true; foreach (Statement statement in statements) { if (statement is ReturnStatement) { bool valid = ValidateReturnStatement((ReturnStatement)statement, table); ok = ok && valid; } else { bool valid = statement.Validate(table); ok = ok && valid; } } return ok; }
public static bool ValidateReturnStatement(ReturnStatement returnStatement, SymbolTableLight table) { bool validReturn = returnStatement.Validate(table); if (validReturn && (returnStatement.Expression != null || f_currentFunction.Header.ReturnType != null) && ( (returnStatement.Expression == null && f_currentFunction.Header.ReturnType != null) || (returnStatement.Expression != null && f_currentFunction.Header.ReturnType == null) || !IsAssignable(f_currentFunction.Header.ReturnType, returnStatement.Expression.ResultType) )) { CompilerServices.AddError( returnStatement.Location, "Return type doesn't match function prototype" ); return false; } return validReturn; }
public static bool ValidateFunctionCall(string name, VAList args, SymbolTableLight table, LexLocation location, ref VariableType returnType) { bool ok = true; List<FunctionHeader> callCandidates = new List<FunctionHeader>(); foreach (FunctionDefinition functionDef in Program.Functions) { if (functionDef.Header.FunctionName == name && functionDef.Header.ParametersCount == args.Count) { callCandidates.Add(functionDef.Header); } } if (callCandidates.Count == 0) { CompilerServices.AddError( location, "Can't find function prototype for specified function name and number of parameters" ); return false; } foreach (Expression ex in args) { bool valid = ex.Validate(table); ok = ok && valid; } if (ok) { foreach (FunctionHeader header in callCandidates) { bool match = true; int i = 0; foreach (FunctionParameter parameter in header.Parameters) { if (!IsAssignable(parameter.Type, args[i].ResultType)) match = false; i++; } if (match) { returnType = header.ReturnType; return true; } } CompilerServices.AddError( location, "Can't find function prototype for specified parameters" ); return false; } return ok; }
public static void SemanticAnalise(L1Program program) { foreach (FunctionDefinition functionDef in program.Functions) { if (functionDef.IsEmbedded) continue; SymbolTableLight table = new SymbolTableLight(); foreach (FunctionParameter parameter in functionDef.Header.Parameters) { SymbolLight symbol = new SymbolLight(parameter.Name, parameter.Type); table.AddSymbol(symbol); } f_currentFunction = functionDef; CheckForLabelsDuplicates(f_currentFunction.Statements); ValidateStatementList(functionDef.Statements, table); if (functionDef.Header.ReturnType != null && !HasReturn(functionDef.Statements)) { CompilerServices.AddError( functionDef.Location, "Not all branches of execution return value" ); } } }