//----------------------------------------------------------- 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); }
//----------------------------------------------------------- public CILGenerator(GlobalSymbolTable gsTable, GlobalProcedureTable gpTable) { GSTable = gsTable; GPTable = gpTable; }