Example #1
0
        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;
        }
Example #3
0
 /// <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;
        }
Example #5
0
        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"
                    );
                }
            }
        }