//-----------------------------------------------------------
        private Type Visit(Identifier node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            var symbolName = node.AnchorToken.Lexeme;

            if (table is GlobalSymbolTable)
            {
                if (gstable.Contains(symbolName))
                {
                    return(gstable[symbolName].TheType);
                }
                throw new SemanticError("Undeclared variable: " + symbolName, node.AnchorToken);
            }
            else if (table is LocalSymbolTable)
            {
                if (lstable.Contains(symbolName))
                {
                    return(lstable[symbolName].LocalType);
                }
                if (GSTable.Contains(symbolName))
                {
                    return(GSTable[symbolName].TheType);
                }
                throw new SemanticError("Undeclared variable: " + symbolName, node.AnchorToken);
            }
            else
            {
                throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
            }
        }
        //-----------------------------------------------------------
        private Type Visit(AssignmentStatement node, Table table)
        {
            Type leftExpressionType  = Visit((dynamic)node[0], table);
            Type rightExpressionType = Visit((dynamic)node[1], table);

            if (leftExpressionType != rightExpressionType)
            {
                if (!((leftExpressionType == Type.LIST_OF_BOOLEAN || leftExpressionType == Type.LIST_OF_INTEGER || leftExpressionType == Type.LIST_OF_STRING) && rightExpressionType == Type.LIST_OF_ANYTHING))
                {
                    throw new SemanticError("Expecting type " + leftExpressionType + " instead of " + rightExpressionType + " in assignment statement", node.AnchorToken);
                }
            }

            if (node[0] is Identifier)
            {
                GlobalSymbolTable gstable = table as GlobalSymbolTable;
                LocalSymbolTable  lstable = table as LocalSymbolTable;

                var symbolName = node[0].AnchorToken.Lexeme;
                if (table is GlobalSymbolTable)
                {
                    if (gstable[symbolName].IsConstant)
                    {
                        throw new SemanticError("Cannot perform assignment to constant " + symbolName, node[0].AnchorToken);
                    }
                }
                else if (table is LocalSymbolTable)
                {
                    if (lstable.Contains(symbolName))
                    {
                        if (lstable[symbolName].Kind == Clasification.CONST)
                        {
                            throw new SemanticError("Cannot perform assignment to constant " + symbolName, node[0].AnchorToken);
                        }
                    }
                    else
                    {
                        if (GSTable.Contains(symbolName) && GSTable[symbolName].IsConstant)
                        {
                            throw new SemanticError("Cannot perform assignment to constant " + symbolName, node[0].AnchorToken);
                        }
                    }
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }
            else if (node[0] is ListIndexExpression)
            {
            }
            else
            {
                throw new TypeAccessException("Expecting either a Idenetifier or a ListIndexExpression " + node[0]);
            }

            return(Type.VOID);
        }
        //-----------------------------------------------------------
        private Type Visit(VariableDeclaration node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            Type declarationType = Visit((dynamic)node[1], table);

            foreach (var n in node[0])
            {
                var symbolName = n.AnchorToken.Lexeme;
                if (table is GlobalSymbolTable)
                {
                    if (GSTable.Contains(symbolName))
                    {
                        throw new SemanticError("Duplicated symbol: " + symbolName, n.AnchorToken);
                    }
                }
                else if (table is LocalSymbolTable)
                {
                    if (lstable.Contains(symbolName))
                    {
                        throw new SemanticError("Duplicated symbol: " + symbolName, n.AnchorToken);
                    }
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }

                if (table is GlobalSymbolTable)
                {
                    gstable[symbolName] = new GlobalSymbol(declarationType);
                }
                else if (table is LocalSymbolTable)
                {
                    lstable[symbolName] = new LocalSymbol(declarationType);
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }

            return(Type.VOID);
        }
        //-----------------------------------------------------------
        private Type Visit(ProcedureDeclaration node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;

            if (table == null)
            {
                throw new TypeAccessException("Expecting a GlobalSymbolTable");
            }

            var procedureName = node.AnchorToken.Lexeme;

            if (gstable.Contains(procedureName))
            {
                throw new SemanticError("Duplicated procedure: " + procedureName, node.AnchorToken);
            }

            if (node[1] is SimpleType || node[1] is ListType)
            {
                GPTable[procedureName] = new GlobalProcedure(false, Visit((dynamic)node[1], table));
                var i = 0;
                foreach (var n in node)
                {
                    if (i != 1)
                    {
                        Visit((dynamic)n, GPTable[procedureName].LocalSymbols);
                    }
                    i++;
                }
            }
            else
            {
                GPTable[procedureName] = new GlobalProcedure(false);
                VisitChildren(node, GPTable[procedureName].LocalSymbols);
            }

            return(Type.VOID);
        }
        //-----------------------------------------------------------
        private Type Visit(ForStatement node, Table table)
        {
            LoopNestingLevel++;

            Type varType = Visit((dynamic)node[0], table);

            var varName = node[0].AnchorToken.Lexeme;
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            if (table is GlobalSymbolTable)
            {
                if (gstable[varName].IsConstant)
                {
                    throw new SemanticError("Loop variable " + varName + " cannot be a constant", node[0].AnchorToken);
                }
            }
            else
            {
                if (lstable.Contains(varName))
                {
                    if (lstable[varName].Kind != Clasification.VAR)
                    {
                        throw new SemanticError("Loop variable " + varName + " cannot be a constant or parameter", node[0].AnchorToken);
                    }
                }
                else
                {
                    if (GSTable[varName].IsConstant)
                    {
                        throw new SemanticError("Loop variable " + varName + " cannot be a constant", node[0].AnchorToken);
                    }
                }
            }

            Type iterableType = Visit((dynamic)node[1], table);

            if (iterableType == Type.LIST_OF_BOOLEAN)
            {
                if (varType != Type.BOOLEAN)
                {
                    throw new SemanticError("Incorrect loop variable \"" + varName + "\". Expecting " + Type.BOOLEAN + ", but found " + varType, node[0].AnchorToken);
                }
            }
            else if (iterableType == Type.LIST_OF_INTEGER)
            {
                if (varType != Type.INTEGER)
                {
                    throw new SemanticError("Incorrect loop variable \"" + varName + "\". Expecting " + Type.INTEGER + ", but found " + varType, node[0].AnchorToken);
                }
            }
            else if (iterableType == Type.LIST_OF_STRING)
            {
                if (varType != Type.STRING)
                {
                    throw new SemanticError("Incorrect loop variable \"" + varName + "\". Expecting " + Type.STRING + ", but found " + varType, node[0].AnchorToken);
                }
            }
            else
            {
                throw new SemanticError("Loop can only iterate over list types, but found " + iterableType, node[1].AnchorToken);
            }

            for (var i = 2; i < node.Count(); i++)
            {
                Visit((dynamic)node[i], table);
            }

            LoopNestingLevel--;
            return(Type.VOID);
        }
        //-----------------------------------------------------------
        public SemanticAnalyzer()
        {
            GSTable = new GlobalSymbolTable();
            GPTable = new GlobalProcedureTable();

            GPTable["WrInt"] = new GlobalProcedure(true, Type.VOID);
            GPTable["WrInt"].LocalSymbols["i"] = new LocalSymbol(0, Type.INTEGER);

            GPTable["WrStr"] = new GlobalProcedure(true, Type.VOID);
            GPTable["WrStr"].LocalSymbols["s"] = new LocalSymbol(0, Type.STRING);

            GPTable["WrBool"] = new GlobalProcedure(true, Type.VOID);
            GPTable["WrBool"].LocalSymbols["b"] = new LocalSymbol(0, Type.BOOLEAN);

            GPTable["WrLn"] = new GlobalProcedure(true, Type.VOID);

            GPTable["RdInt"] = new GlobalProcedure(true, Type.INTEGER);

            GPTable["RdStr"] = new GlobalProcedure(true, Type.STRING);

            GPTable["AtStr"] = new GlobalProcedure(true, Type.STRING);
            GPTable["AtStr"].LocalSymbols["s"] = new LocalSymbol(0, Type.STRING);
            GPTable["AtStr"].LocalSymbols["i"] = new LocalSymbol(1, Type.INTEGER);

            GPTable["LenStr"] = new GlobalProcedure(true, Type.INTEGER);
            GPTable["LenStr"].LocalSymbols["s"] = new LocalSymbol(0, Type.STRING);

            GPTable["CmpStr"] = new GlobalProcedure(true, Type.INTEGER);
            GPTable["CmpStr"].LocalSymbols["s1"] = new LocalSymbol(0, Type.STRING);
            GPTable["CmpStr"].LocalSymbols["s2"] = new LocalSymbol(1, Type.STRING);

            GPTable["CatStr"] = new GlobalProcedure(true, Type.STRING);
            GPTable["CatStr"].LocalSymbols["s1"] = new LocalSymbol(0, Type.STRING);
            GPTable["CatStr"].LocalSymbols["s2"] = new LocalSymbol(1, Type.STRING);

            GPTable["LenLstInt"] = new GlobalProcedure(true, Type.INTEGER);
            GPTable["LenLstInt"].LocalSymbols["loi"] = new LocalSymbol(0, Type.LIST_OF_INTEGER);

            GPTable["LenLstStr"] = new GlobalProcedure(true, Type.INTEGER);
            GPTable["LenLstStr"].LocalSymbols["los"] = new LocalSymbol(0, Type.LIST_OF_STRING);

            GPTable["LenLstBool"] = new GlobalProcedure(true, Type.INTEGER);
            GPTable["LenLstBool"].LocalSymbols["lob"] = new LocalSymbol(0, Type.LIST_OF_BOOLEAN);

            GPTable["NewLstInt"] = new GlobalProcedure(true, Type.LIST_OF_INTEGER);
            GPTable["NewLstInt"].LocalSymbols["size"] = new LocalSymbol(0, Type.INTEGER);

            GPTable["NewLstStr"] = new GlobalProcedure(true, Type.LIST_OF_STRING);
            GPTable["NewLstStr"].LocalSymbols["size"] = new LocalSymbol(0, Type.INTEGER);

            GPTable["NewLstBool"] = new GlobalProcedure(true, Type.LIST_OF_BOOLEAN);
            GPTable["NewLstBool"].LocalSymbols["size"] = new LocalSymbol(0, Type.INTEGER);

            GPTable["IntToStr"] = new GlobalProcedure(true, Type.STRING);
            GPTable["IntToStr"].LocalSymbols["i"] = new LocalSymbol(0, Type.INTEGER);

            GPTable["StrToInt"] = new GlobalProcedure(true, Type.INTEGER);
            GPTable["StrToInt"].LocalSymbols["s"] = new LocalSymbol(0, Type.STRING);


            LoopNestingLevel = 0;
        }
        //-----------------------------------------------------------
        private Type Visit(ConstantDeclaration node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            var symbolName = node.AnchorToken.Lexeme;

            if (table is GlobalSymbolTable)
            {
                if (GSTable.Contains(symbolName))
                {
                    throw new SemanticError("Duplicated symbol: " + symbolName, node[0].AnchorToken);
                }
            }
            else if (table is LocalSymbolTable)
            {
                if (lstable.Contains(symbolName))
                {
                    throw new SemanticError("Duplicated symbol: " + symbolName, node[0].AnchorToken);
                }
            }
            else
            {
                throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
            }

            Type nodeType = Visit((dynamic)node[0], table);

            if (node[0] is Lst)
            {
                if (node[0].Count() == 0)
                {
                    throw new SemanticError("Constant lists cannot be empty: " + symbolName, node.AnchorToken);
                }

                dynamic lst;
                if (nodeType == Type.LIST_OF_BOOLEAN)
                {
                    lst = new Boolean[node[0].Count()];
                }
                else if (nodeType == Type.LIST_OF_INTEGER)
                {
                    lst = new Int32[node[0].Count()];
                }
                else if (nodeType == Type.LIST_OF_STRING)
                {
                    lst = new String[node[0].Count()];
                }
                else
                {
                    throw new TypeAccessException("Expecting one of the following node types: LIST_OF_BOOLEAN, LIST_OF_INTEGER, LIST_OF_STRING");
                }

                int i = 0;
                foreach (var n in node[0])
                {
                    lst[i++] = n.ExtractValue();
                }
                if (table is GlobalSymbolTable)
                {
                    gstable[symbolName] = new GlobalSymbol(nodeType, lst);
                }
                else if (table is LocalSymbolTable)
                {
                    lstable[symbolName] = new LocalSymbol(nodeType, lst);
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }
            else
            {
                if (table is GlobalSymbolTable)
                {
                    gstable[symbolName] = new GlobalSymbol(nodeType, node[0].ExtractValue());
                }
                else if (table is LocalSymbolTable)
                {
                    lstable[symbolName] = new LocalSymbol(nodeType, node[0].ExtractValue());
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }

            return(Type.VOID);
        }
示例#8
0
 //-----------------------------------------------------------
 public CILGenerator(GlobalSymbolTable gsTable, GlobalProcedureTable gpTable)
 {
     GSTable = gsTable;
     GPTable = gpTable;
 }