/********************************************************************** * Functions and Subroutines * *******************************************************************/ //----------------------------------------------------------- public Type Visit(Function node) { string functionKeyword = node.AnchorToken.Lexeme; if (!Tables.ContainsKey(functionKeyword)) { Tables.Add(functionKeyword, new List <SymbolTable>()); } Tables[functionKeyword].Add(new SymbolTable()); progUnit = functionKeyword; var functionTable = Tables[progUnit].Last(); string funcName = node[1].AnchorToken.Lexeme; functionTable[funcName] = new SymbolEntry(typeMapper[node[0].AnchorToken.Category]); return(Type.VOID); }
//----------------------------------------------------------- public Type Visit(Parameter node) { var paramAssgn = node[0]; var variableName = paramAssgn[0].AnchorToken.Lexeme; var currentTable = Tables[progUnit].Last(); if (IdHasBeenFound(variableName)) { if (!currentTable.Contains(variableName)) { currentTable[variableName] = new SymbolEntry(GetIdType(variableName)); } else { if (currentTable[variableName].IsConstant) { throw new SemanticError( "A variable can only be used in one parameter: " + variableName, paramAssgn[0].AnchorToken); } } currentTable[variableName].IsConstant = true; var expectedType = currentTable[variableName].SymbolType; var foundType = Visit((dynamic)paramAssgn[1]); if (expectedType != foundType) { throw new SemanticError( "Expecting type " + expectedType + " in assignment statement.", paramAssgn[0].AnchorToken); } } else { throw new SemanticError( "Undeclared variable: " + variableName, paramAssgn[0].AnchorToken); } return(Type.VOID); }
//----------------------------------------------------------- public Type Visit(Declaration node) { var currentTable = Tables[progUnit].Last(); foreach (var decl in node) { var variableName = decl.AnchorToken.Lexeme; if (currentTable.Contains(variableName)) { throw new SemanticError( "Duplicated variable: " + variableName, decl.AnchorToken); } else { currentTable[variableName] = new SymbolEntry(typeMapper[node.AnchorToken.Category]); if (decl.HasChildren()) { var declArray = decl[0]; if (declArray.NodeChildrenCount() > 2) { throw new SemanticError( "An array can have 2 dimensions at most: " + variableName, decl.AnchorToken); } for (int i = 0; i < declArray.NodeChildrenCount(); i++) { if (Visit((dynamic)declArray[i]) != Type.INTEGER) { throw new SemanticError( "Only integers can be used as Array dimensions.", declArray[i].AnchorToken); } if (declArray[i].AnchorToken.Category == TokenCategory.IDENTIFIER) { var dimName = declArray[i].AnchorToken.Lexeme; if (!currentTable.Contains(dimName)) { throw new SemanticError( "Undeclared dimension: " + dimName, declArray[i].AnchorToken); } if (!currentTable[dimName].IsConstant) { throw new SemanticError( "Cannot use non-constant variables as" + " array dimensions.", declArray[i].AnchorToken); } } currentTable[variableName].Params .Add(declArray[i].AnchorToken.Lexeme); } } } } return(Type.VOID); }